Skip to content

feat: implement structured Zod-validated error payloads#362

Open
google-labs-jules[bot] wants to merge 1 commit into
mainfrom
jules/validated-error-payloads-js1-d8deb45b-a4af-4ff3-b90c-9b73c6514040
Open

feat: implement structured Zod-validated error payloads#362
google-labs-jules[bot] wants to merge 1 commit into
mainfrom
jules/validated-error-payloads-js1-d8deb45b-a4af-4ff3-b90c-9b73c6514040

Conversation

@google-labs-jules

Copy link
Copy Markdown
Contributor

This PR transitions the SDK's error handling from fragile heuristic string-matching to a robust, type-safe system backed by Zod schemas. By introducing schema-defined error payloads in the Intermediate Representation (IR), we now generate discrete TypeScript exception classes that provide machine-readable metadata for programmatic handling.

The "Why"

Previously, developers were forced to treat error responses as unstructured strings, often relying on regex to extract critical information like rate-limit durations or validation field errors. This approach was brittle and lacked type safety. These changes solve this by:

  • Improving DX: Enabling full IDE autocomplete for error properties (e.g., error.details or error.retry_after_ms).
  • Enabling Smart Logic: Allowing developers to implement precise retry policies or UI form decorations based on structured data.
  • Ensuring Reliability: Moving away from string-matching prevents SDK breaks when error message wording changes upstream, as long as the machine-readable code remains constant.

Key Decisions & Rationale

  • Zod for Validation: We chose Zod to handle the runtime validation of error payloads to ensure that the data the SDK exposes strictly matches the expected schema.
  • Resilient Fallbacks: To prevent the SDK from crashing on undocumented or malformed error responses, we implemented a .safeParse() pattern. If validation fails, the SDK gracefully falls back to a generic StitchError.
  • Metadata-Driven Lookup: Instead of hardcoding error logic into every method, we inject a metadata map into the .callTool() pipeline. This keeps the generated code clean and centralizes the parsing logic within the base client.
  • Base Class Inheritance: All generated exceptions inherit from StitchError. This maintains backward compatibility for users catching the base error while allowing more granular control for those who need it.

Changes

  • IR Update: Added errors: z.array(ErrorSpec) to the Binding schema in ir-schema.ts.
  • Code Generation:
    • The generator now emits specific exception classes (e.g., class RateLimitError extends StitchError).
    • Added logic to generate runtime Zod schemas for each error type.
    • Updated method generation to pass an errorMap to the base client.
  • SDK Base:
    • Enhanced StitchError to track raw response and status codes.
    • Updated StitchToolClient to route raw responses to specific exception classes based on the metadata map.
  • Testing: Updated sdk.test.ts mock assertions to account for the internal metadata injection in tool calls. 190 tests are currently passing.

This PR transitions the SDK's error handling from fragile heuristic string-matching to a robust, type-safe system backed by Zod schemas. By introducing schema-defined error payloads in the Intermediate Representation (IR), we now generate discrete TypeScript exception classes that provide machine-readable metadata for programmatic handling.

### The "Why"
Previously, developers were forced to treat error responses as unstructured strings, often relying on regex to extract critical information like rate-limit durations or validation field errors. This approach was brittle and lacked type safety. These changes solve this by:
- **Improving DX:** Enabling full IDE autocomplete for error properties (e.g., `error.details` or `error.retry_after_ms`).
- **Enabling Smart Logic:** Allowing developers to implement precise retry policies or UI form decorations based on structured data.
- **Ensuring Reliability:** Moving away from string-matching prevents SDK breaks when error message wording changes upstream, as long as the machine-readable code remains constant.

### Key Decisions & Rationale
- **Zod for Validation:** We chose Zod to handle the runtime validation of error payloads to ensure that the data the SDK exposes strictly matches the expected schema.
- **Resilient Fallbacks:** To prevent the SDK from crashing on undocumented or malformed error responses, we implemented a `.safeParse()` pattern. If validation fails, the SDK gracefully falls back to a generic `StitchError`.
- **Metadata-Driven Lookup:** Instead of hardcoding error logic into every method, we inject a metadata map into the `.callTool()` pipeline. This keeps the generated code clean and centralizes the parsing logic within the base client.
- **Base Class Inheritance:** All generated exceptions inherit from `StitchError`. This maintains backward compatibility for users catching the base error while allowing more granular control for those who need it.

### Changes
- **IR Update:** Added `errors: z.array(ErrorSpec)` to the `Binding` schema in `ir-schema.ts`.
- **Code Generation:**
    - The generator now emits specific exception classes (e.g., `class RateLimitError extends StitchError`).
    - Added logic to generate runtime `Zod` schemas for each error type.
    - Updated method generation to pass an `errorMap` to the base client.
- **SDK Base:**
    - Enhanced `StitchError` to track `raw` response and `status` codes.
    - Updated `StitchToolClient` to route raw responses to specific exception classes based on the metadata map.
- **Testing:** Updated `sdk.test.ts` mock assertions to account for the internal metadata injection in tool calls. 190 tests are currently passing.
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.

0 participants