Skip to content

feat(ai-sdk): disable validation at oRPC level in createTool to avoid double validation#1166

Merged
dinwwwh merged 2 commits intomainfrom
feat/ai-sdk/disable-validation-at-oRPC-level-in-createTool
Nov 5, 2025
Merged

feat(ai-sdk): disable validation at oRPC level in createTool to avoid double validation#1166
dinwwwh merged 2 commits intomainfrom
feat/ai-sdk/disable-validation-at-oRPC-level-in-createTool

Conversation

@dinwwwh
Copy link
Copy Markdown
Member

@dinwwwh dinwwwh commented Nov 4, 2025

Refactors validation handling in tool creation by setting input/output validation indices to NaN, replacing the previous proxy-based approach. This prevents validation from occurring twice - once at the tool level and once at the procedure call level - which was causing issues when schemas transform data into different shapes. Includes test coverage for the new validation disabling behavior and updates related tRPC integration to use the same approach.

Summary by CodeRabbit

  • New Features

    • Tool execution now forwards abort/cancel signals and accepts calling options for finer control.
    • Added support to disable input/output validation when desired for flexible handling.
  • Documentation

    • Simplified docs and removed a redundant validation warning for clearer guidance.
  • Tests

    • Expanded tests covering abort-signal propagation and disabled-validation scenarios.

… double validation

Refactors validation handling in tool creation by setting input/output validation indices to NaN, replacing the previous proxy-based approach. This prevents validation from occurring twice - once at the tool level and once at the procedure call level - which was causing issues when schemas transform data into different shapes. Includes test coverage for the new validation disabling behavior and updates related tRPC integration to use the same approach.
@vercel
Copy link
Copy Markdown

vercel bot commented Nov 4, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
orpc Ready Ready Preview Comment Nov 4, 2025 7:53am

@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Nov 4, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 4, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Refactors tool execution to accept calling options (including an abort signal), wraps calls with a temporary Procedure configured to disable oRPC input/output validation via NaN indices, updates related imports and tests, and updates docs to remove a duplicate-validation warning.

Changes

Cohort / File(s) Summary
Documentation Updates
apps/content/docs/integrations/ai-sdk.md
Adds placeholder comments for configuration overrides and removes an inline warning about duplicate validation.
Tool Implementation
packages/ai-sdk/src/tool.ts
Changes createTool/execute to accept (input, callingOptions), propagates abortSignal, wraps execution with a Procedure configured with inputValidationIndex/outputValidationIndex = NaN, and updates imports to include Procedure.
Tool Tests
packages/ai-sdk/src/tool.test.ts
Makes tool tests asynchronous, passes an abortSignal through execute calls and asserts it reaches handlers; adds a test for disabling input validation at the oRPC level.
Procedure Validation Tests
packages/server/src/procedure-client.test.ts
Adds a test confirming that setting inputValidationIndex and outputValidationIndex to NaN disables validation and allows invalid inputs to pass through.
tRPC Router Integration
packages/trpc/src/to-orpc-router.ts
Replaces previous no-validation proxy approach with NaN indices to disable validation and switches from toDisabledStandardSchema to toStandardSchema; adjusts schema typing access.
tRPC Router Tests
packages/trpc/src/to-orpc-router.test.ts
Renames test for clarity, constructs a Procedure in-test to bypass oRPC validation, and asserts inputValidationIndex/outputValidationIndex are NaN while tRPC-level validation still rejects invalid input.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant Tool
    participant Wrapper as Procedure (NaN indices)
    participant CallClient as oRPC call
    participant Handler

    Caller->>Tool: execute(input, { abortSignal })
    Tool->>Wrapper: create Procedure with inputValidationIndex=NaN / outputValidationIndex=NaN
    Tool->>Wrapper: call(input, { abortSignal })
    Wrapper->>CallClient: invoke underlying call (propagate abortSignal)
    CallClient->>Handler: execute handler with abortSignal
    Handler-->>CallClient: result
    CallClient-->>Wrapper: result
    Wrapper-->>Tool: result
    Tool-->>Caller: Promise<result>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to packages/ai-sdk/src/tool.ts (execute signature, typing via satisfies, abortSignal propagation).
  • Verify packages/trpc/src/to-orpc-router.ts changes for NaN-based disabling and schema handling.
  • Review new/updated tests in packages/ai-sdk, packages/server, and packages/trpc for correctness and flakiness.

Possibly related PRs

  • unnoq/orpc#1163 — touches NaN-based validation disabling and tests related to procedure validation control.
  • unnoq/orpc#699 — modifies how Procedure validation is disabled and alters to-orpc-router behavior; closely related to these changes.

Suggested labels

size:XL

Poem

🐰 I hopped through code with signal in paw,
Switched guards to NaN and fixed the law,
Handlers now hear the abort’s bright call,
Validation sleeps — no errors fall,
A joyful hop, a tidy crawl!

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: disabling validation at the oRPC level in createTool to prevent double validation, which aligns with the primary objective of the PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/ai-sdk/disable-validation-at-oRPC-level-in-createTool

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 883845e and e26a3eb.

📒 Files selected for processing (1)
  • packages/ai-sdk/src/tool.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/ai-sdk/src/tool.ts (1)
packages/server/src/procedure.ts (1)
  • Procedure (55-71)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: publish-commit
  • GitHub Check: test
  • GitHub Check: lint
🔇 Additional comments (2)
packages/ai-sdk/src/tool.ts (2)

3-3: LGTM! Import changes align with new usage.

The addition of Procedure as a value import is necessary for constructing procedure instances with disabled validation on line 149.

Also applies to: 6-6


155-159: Based on my verification of the script output and web research:

NaN Handling is Correct: The validation indices are clamped with Math.min(Math.max(0, procedure['~orpc'].inputValidationIndex), middlewares.length), which converts Number.NaN to NaN, and since NaN !== NaN is always true, the validation checks at lines 234 and 268 never execute when indices are NaN, effectively disabling validation as intended.

Type Safety Concern Remains Valid: Schema input and output types can diverge—for instance, the .transform() API can convert the input from one type to another. When validation is disabled via NaN indices and the code sets inputValidationIndex: Number.NaN and outputValidationIndex: Number.NaN, transformed data bypasses validation, making the type casts at lines 157 and 159 potentially unsafe if schemas apply transformations.

Recommendation: Verify whether the ORPC framework's schema implementation supports data transformations like Zod's .transform() API, and ensure the disabled validation approach is intentional and documented when used with transforming schemas.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @unnoq, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request streamlines the validation process for tools integrated with oRPC by eliminating redundant validation steps. Previously, tools could undergo validation twice, leading to potential issues with data transformation. The changes ensure that validation occurs only where intended, improving consistency and preventing unexpected failures, particularly in scenarios involving complex schema transformations.

Highlights

  • Validation Refactoring: The pull request refactors validation handling within the createTool function by explicitly disabling oRPC-level validation.
  • Double Validation Prevention: It addresses an issue where validation was occurring twice (once at the tool level and once at the procedure call level), which could cause problems when schemas transform data.
  • Implementation Detail: Validation is now disabled by setting inputValidationIndex and outputValidationIndex to Number.NaN in the underlying oRPC Procedure.
  • Proxy Removal: This new approach replaces a previous proxy-based method for disabling validation in tRPC integration.
  • Test Coverage: New test cases have been added to verify the correct behavior of disabled validation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant improvement by disabling validation at the oRPC level in createTool to prevent double validation, which is a cleaner approach than the previous proxy-based method. The changes are well-implemented across the ai-sdk and trpc packages, with corresponding updates to tests and documentation. However, I've identified a critical typing issue in packages/ai-sdk/src/tool.ts where a type cast incorrectly removes the Promise type from a return value, which could lead to runtime errors.

@codecov
Copy link
Copy Markdown

codecov bot commented Nov 4, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Nov 4, 2025

More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1166

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1166

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1166

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1166

@orpc/experimental-durable-iterator

npm i https://pkg.pr.new/@orpc/experimental-durable-iterator@1166

@orpc/hey-api

npm i https://pkg.pr.new/@orpc/hey-api@1166

@orpc/interop

npm i https://pkg.pr.new/@orpc/interop@1166

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1166

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1166

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1166

@orpc/openapi-client

npm i https://pkg.pr.new/@orpc/openapi-client@1166

@orpc/otel

npm i https://pkg.pr.new/@orpc/otel@1166

@orpc/experimental-publisher

npm i https://pkg.pr.new/@orpc/experimental-publisher@1166

@orpc/react

npm i https://pkg.pr.new/@orpc/react@1166

@orpc/react-query

npm i https://pkg.pr.new/@orpc/react-query@1166

@orpc/experimental-react-swr

npm i https://pkg.pr.new/@orpc/experimental-react-swr@1166

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1166

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1166

@orpc/solid-query

npm i https://pkg.pr.new/@orpc/solid-query@1166

@orpc/standard-server

npm i https://pkg.pr.new/@orpc/standard-server@1166

@orpc/standard-server-aws-lambda

npm i https://pkg.pr.new/@orpc/standard-server-aws-lambda@1166

@orpc/standard-server-fastify

npm i https://pkg.pr.new/@orpc/standard-server-fastify@1166

@orpc/standard-server-fetch

npm i https://pkg.pr.new/@orpc/standard-server-fetch@1166

@orpc/standard-server-node

npm i https://pkg.pr.new/@orpc/standard-server-node@1166

@orpc/standard-server-peer

npm i https://pkg.pr.new/@orpc/standard-server-peer@1166

@orpc/svelte-query

npm i https://pkg.pr.new/@orpc/svelte-query@1166

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1166

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1166

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1166

@orpc/vue-colada

npm i https://pkg.pr.new/@orpc/vue-colada@1166

@orpc/vue-query

npm i https://pkg.pr.new/@orpc/vue-query@1166

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1166

commit: e26a3eb

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c5f175 and 883845e.

📒 Files selected for processing (6)
  • apps/content/docs/integrations/ai-sdk.md (2 hunks)
  • packages/ai-sdk/src/tool.test.ts (3 hunks)
  • packages/ai-sdk/src/tool.ts (2 hunks)
  • packages/server/src/procedure-client.test.ts (1 hunks)
  • packages/trpc/src/to-orpc-router.test.ts (2 hunks)
  • packages/trpc/src/to-orpc-router.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
packages/server/src/procedure-client.test.ts (3)
packages/server/src/procedure.ts (1)
  • Procedure (55-71)
packages/server/src/builder.ts (1)
  • input (243-251)
packages/server/src/procedure-client.ts (1)
  • createProcedureClient (72-165)
packages/ai-sdk/src/tool.test.ts (1)
packages/ai-sdk/src/tool.ts (1)
  • createTool (131-163)
packages/trpc/src/to-orpc-router.test.ts (2)
packages/contract/tests/shared.ts (2)
  • inputSchema (6-6)
  • outputSchema (8-8)
packages/server/src/procedure.ts (1)
  • Procedure (55-71)
packages/trpc/src/to-orpc-router.ts (1)
packages/shared/src/object.ts (1)
  • isTypescriptObject (57-59)
packages/ai-sdk/src/tool.ts (1)
packages/server/src/procedure.ts (1)
  • Procedure (55-71)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: publish-commit
  • GitHub Check: lint
  • GitHub Check: test
🔇 Additional comments (8)
packages/trpc/src/to-orpc-router.ts (1)

94-98: NaN sentinel cleanly disables duplicate validation

Swapping the proxy for NaN indices keeps schema metadata intact while letting tRPC remain authoritative on parsing.

apps/content/docs/integrations/ai-sdk.md (1)

163-165: Helpful inline hint

The placeholder makes future overrides clearer without altering current behavior.

packages/server/src/procedure-client.test.ts (1)

656-672: Great coverage for the NaN sentinel

Nice regression test confirming that bypassing validation via NaN pipes raw input through exactly as designed.

packages/ai-sdk/src/tool.test.ts (1)

84-129: Tool tests capture abort + no-validation flow

Async execute plus the invalid-input assertion line up perfectly with the new createTool behavior.

packages/trpc/src/to-orpc-router.test.ts (1)

34-50: Test proves TRPC keeps validation while oRPC skips

Asserting both the NaN indices and the divergent call outcomes gives great confidence in the bridge.

packages/ai-sdk/src/tool.ts (3)

157-159: Type casts are necessary but verify AI SDK performs validation.

The type casts on lines 157 and 159 bypass TypeScript's type safety. This is necessary because disabling oRPC validation creates a type mismatch—the AI SDK validates the input/output using schemas, producing types that don't perfectly align with oRPC's expectations. Ensure that the AI SDK properly validates both input and output, as oRPC validation is now disabled.


160-160: Good use of satisfies for type safety.

The satisfies constraint ensures the execute function matches the expected Tool signature while preserving type inference. This is a robust approach to maintain type safety.


149-153: I need to examine how the next function is called to verify whether the NaN approach actually works correctly:

Now let me check how the next function is invoked to understand the full middleware loop:

Review comment needs clarification: NaN-based disablement technically works but relies on unintuitive JavaScript behavior.

The implementation does disable validation, but the mechanism is fragile. When comparing numbers, they're considered equal only if both are not NaN, and NaN compares unequal to any other value — including to another NaN value. When inputValidationIndex and outputValidationIndex are set to Number.NaN, the equality checks at lines 234 and 268 of procedure-client.ts (if (index === inputValidationIndex)) will never match any numeric index, thus skipping validation.

However, this approach relies on NaN's implicit comparison behavior rather than an explicit sentinel pattern. Math.min and Math.max return NaN if any parameter is or is converted into NaN, so the clamping operation preserves NaN correctly. The pattern works as intended but lacks clarity—using an explicit value like -1 with a dedicated check would be more maintainable and self-documenting.

No actual issues were found with the implementation, but the review comment's verification request has been satisfied: the NaN-based approach does prevent validation execution as designed.

@dinwwwh dinwwwh added the lgtm This PR has been approved by a maintainer label Nov 4, 2025
@dinwwwh dinwwwh merged commit 3bec7fc into main Nov 5, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant