Skip to content

Replace array_map with Parse::to_list for robust list parsing - #489

Draft
razor-x wants to merge 2 commits into
mainfrom
claude/sdk-webhook-union-resilience-mu1ldf
Draft

Replace array_map with Parse::to_list for robust list parsing#489
razor-x wants to merge 2 commits into
mainfrom
claude/sdk-webhook-union-resilience-mu1ldf

Conversation

@razor-x

@razor-x razor-x commented Sep 1, 2026

Copy link
Copy Markdown
Member

Summary

This change improves the robustness of JSON parsing throughout the SDK by replacing direct array_map calls with a new Parse::to_list helper method. This prevents TypeErrors when the API sends list properties as scalars or null values, allowing responses to degrade gracefully instead of failing entirely.

Key Changes

  • New Parse::to_list helper: Created src/Parse.php with a utility method that safely converts values to lists, returning an empty array if the value is not an array. This prevents array_map TypeErrors when encountering unexpected data shapes.

  • Updated all resource classes: Replaced array_map($callback, $json->property ?? []) patterns with Parse::to_list($json->property ?? null, $callback) across all resource files including:

    • Event, Device, AccessCode, AccessGrant, ConnectedAccount, AcsUser, AcsEntrance, and many others
    • ActionAttempt and its nested structures
    • All other resource types that parse list properties
  • New error class: Added ActionAttemptUnknownStatusError in src/ActionAttemptUnknownStatusError.php to handle action attempts with unrecognized status values. This prevents the polling mechanism from incorrectly claiming success or timing out when encountering new status codes added after the SDK release.

  • Updated polling logic: Modified src/Http/ResolveActionAttempt.php to throw ActionAttemptUnknownStatusError when encountering an unrecognized status during polling, rather than treating it as pending.

  • Comprehensive test coverage: Added tests/TotalParsingTest.php with test cases covering:

    • List properties sent as scalars
    • List properties sent as null
    • Unknown error codes within lists
    • Nested objects sent as scalars
    • Unknown event types
    • Unknown action attempt statuses
  • Updated code generator: Modified codegen/lib/layouts/resource.ts to generate the new Parse::to_list pattern for future resource generation.

Implementation Details

The Parse::to_list method provides a single point of control for safe list parsing, ensuring that any unexpected data shape (scalar, null, or other non-array value) degrades to an empty list rather than raising an exception. This aligns with the SDK's philosophy of never failing the entire response over a single field, allowing callers to work with partial data when the API sends unexpected shapes.

https://claude.ai/code/session_01M2kJ4nGaM8imZCVMEKjmXA

…uses

Seam adds event types, action types, and error codes between SDK releases, so a
payload this version does not recognize should stay readable rather than cost
the caller the whole response.

A list property the API sends as a scalar no longer fails the whole response.
The generated classes mapped these with array_map, which raises a TypeError when
handed anything but an array, so a single unexpected field took down every other
field alongside it. They now route through Seam\Parse::to_list, which reads a
non-list as empty.

Waiting on an action attempt whose status is neither pending, success, nor error
raises the new ActionAttemptUnknownStatusError. The resolver previously treated
an unrecognized status as non-terminal and polled until the deadline, then
reported a timeout that misdescribed what happened. The error subclasses
ActionAttemptError, so existing handlers for that base keep working.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M2kJ4nGaM8imZCVMEKjmXA
The added comments ran to roughly double the density of the code around them and
mostly restated what the line below already said. Kept the ones carrying
information the code cannot: why svix/util has to be required, why both key
shapes are accepted after symbolize_names, and why array_map needed replacing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M2kJ4nGaM8imZCVMEKjmXA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants