Summary
Rendering a block with an array-valued className can trigger a frontend fatal error while Otter checks whether the block uses sticky behavior.
Expected behavior: Block rendering continues when a block has an unexpected or malformed className attribute.
Actual behavior: Rendering terminates with TypeError: strpos(): Argument #1 ($haystack) must be of type string, array given.
Impact: The affected page cannot render until the triggering block data is avoided or corrected.
Customer context
- Product / area: Otter Blocks sticky asset loading
- Version: 3.0.12
- Environment: WordPress 7.1; PHP 8.3.32; frontend request
- Integration / third party: Theme JNews appears in the reported render stack
- Reported error / symptom:
TypeError: strpos(): Argument #1 ($haystack) must be of type string, array given
- Impact: 3 occurrences across 1 site in the telemetry query window.
Reproduction notes
- In a WordPress frontend request with Otter active, render a block whose parsed attributes include
className as an array.
- The global
render_block callback reaches the sticky asset loader.
- In version 3.0.12, the reported
strpos() TypeError is expected from the tagged code path.
Production reproduction is confirmed by telemetry; the source of the malformed attribute is not provided.
Diagnosis
Conclusion
Production telemetry identifies Registration::load_sticky() as the throwing frame in Otter Blocks 3.0.12. The tagged release invokes strpos() on block['attrs']['className'] after testing only for presence, so an array reaches a function that requires a string. This directly matches the captured TypeError. The source editor path normally serializes the sticky classes as a string, indicating the crash requires unexpected or malformed block attribute data, but the frontend handler lacks a safe boundary for it.
Where this likely occurs
inc/class-registration.php — Registration::init() lines 103-113 registers Registration::load_sticky() on the global render_block filter at priority 900, making the handler run during frontend block rendering.
inc/class-registration.php — Registration::load_sticky() lines 1115-1136; line 1120 checks only isset() before passing attrs.className to strpos().
- Release
v3.0.12 contains the equivalent call at inc/class-registration.php — Registration::load_sticky() lines 978-1000, with the call at line 983, matching the telemetry location exactly.
inc/class-registration.php — Registration::load_sticky() line 1120 traces by blame to commit 39d7d75ac (2022-07-22); the relevant expression remains unchanged between v3.0.12 and the inspected checkout.
Engineering notes
- The telemetry marks this as product code rather than bundled Themeisle SDK code, so the issue routes to
Codeinwp/otter-blocks.
src/blocks/plugins/sticky/index.js — toggleSticky() lines 22-35 and StickyExtension() lines 37-60 construct and save a space-delimited string for normal editor interactions. That workflow does not explain the array value, but it confirms the frontend path is exposed to block attributes that may originate outside this UI.
- The captured trace runs through WordPress block rendering. WordPress core source was not present in the inspected workspace, so the parsed-block attribute shape beyond the telemetry evidence was not independently verified.
Test coverage status
No sticky-specific test files were found under src/blocks/test, and no PHP tests referencing load_sticky or o-sticky were found during inspection. Existing editor code was inspected, but no test covering non-string className input was located.
What to verify or explore next
- Reproduce rendering a parsed block whose
attrs.className is an array while the sticky render filter is active.
- Run the relevant PHP test suite after adding or locating coverage for
Registration::load_sticky().
- Check whether imported content, reusable blocks, or third-party block transformations can persist an array-valued
className attribute.
Unknowns / follow-up
- The telemetry does not include the serialized block markup or identify the block that carried the array-valued attribute.
- It is unknown whether the malformed attribute was authored by a third-party integration, imported content, or persisted historical data.
Confidence
Confidence: 98/100
Production telemetry records three frontend crashes on one site in Otter Blocks 3.0.12, and the tagged source passes attrs.className to PHP strpos() without checking that it is a string. The stack location and reported TypeError directly match that call.
Crash telemetry
|
|
| Occurrences |
3 |
| Distinct sites |
1 |
| First seen |
2026-08-22 12:36 UTC |
| Last seen |
2026-08-23 22:40 UTC |
| Crash location |
product:inc/class-registration.php:983 |
| Request context |
frontend |
| Inside Themeisle SDK |
no |
| Product versions |
3.0.12 |
| WP versions |
7.1 |
| PHP versions |
8.3.32 |
| SDK versions |
3.3.58 |
Source: automated crash report — otter-blocks, fingerprint ad8f3634cd6915f569a5456ff8295b76
Generated by bug-report-triage (ID: bug-report-triage_6a8bde12ae2b84.43414214)
Summary
Rendering a block with an array-valued
classNamecan trigger a frontend fatal error while Otter checks whether the block uses sticky behavior.Expected behavior: Block rendering continues when a block has an unexpected or malformed
classNameattribute.Actual behavior: Rendering terminates with
TypeError: strpos(): Argument #1 ($haystack) must be of type string, array given.Impact: The affected page cannot render until the triggering block data is avoided or corrected.
Customer context
TypeError: strpos(): Argument #1 ($haystack) must be of type string, array givenReproduction notes
classNameas an array.render_blockcallback reaches the sticky asset loader.strpos()TypeError is expected from the tagged code path.Production reproduction is confirmed by telemetry; the source of the malformed attribute is not provided.
Diagnosis
Conclusion
Production telemetry identifies
Registration::load_sticky()as the throwing frame in Otter Blocks 3.0.12. The tagged release invokesstrpos()onblock['attrs']['className']after testing only for presence, so an array reaches a function that requires a string. This directly matches the captured TypeError. The source editor path normally serializes the sticky classes as a string, indicating the crash requires unexpected or malformed block attribute data, but the frontend handler lacks a safe boundary for it.Where this likely occurs
inc/class-registration.php—Registration::init()lines 103-113 registersRegistration::load_sticky()on the globalrender_blockfilter at priority 900, making the handler run during frontend block rendering.inc/class-registration.php—Registration::load_sticky()lines 1115-1136; line 1120 checks onlyisset()before passingattrs.classNametostrpos().v3.0.12contains the equivalent call atinc/class-registration.php—Registration::load_sticky()lines 978-1000, with the call at line 983, matching the telemetry location exactly.inc/class-registration.php—Registration::load_sticky()line 1120 traces by blame to commit39d7d75ac(2022-07-22); the relevant expression remains unchanged betweenv3.0.12and the inspected checkout.Engineering notes
Codeinwp/otter-blocks.src/blocks/plugins/sticky/index.js—toggleSticky()lines 22-35 andStickyExtension()lines 37-60 construct and save a space-delimited string for normal editor interactions. That workflow does not explain the array value, but it confirms the frontend path is exposed to block attributes that may originate outside this UI.Test coverage status
No sticky-specific test files were found under
src/blocks/test, and no PHP tests referencingload_stickyoro-stickywere found during inspection. Existing editor code was inspected, but no test covering non-stringclassNameinput was located.What to verify or explore next
attrs.classNameis an array while the sticky render filter is active.Registration::load_sticky().classNameattribute.Unknowns / follow-up
Confidence
Confidence: 98/100
Production telemetry records three frontend crashes on one site in Otter Blocks 3.0.12, and the tagged source passes
attrs.classNameto PHPstrpos()without checking that it is a string. The stack location and reported TypeError directly match that call.Crash telemetry
product:inc/class-registration.php:983Source: automated crash report — otter-blocks, fingerprint
ad8f3634cd6915f569a5456ff8295b76Generated by bug-report-triage (ID: bug-report-triage_6a8bde12ae2b84.43414214)