TanStack / TanStack/ai

Type conflict: @ag-ui/core 0.0.49 (Zod 3) breaks consumer Zod 4 type checking

Open
#520 3 comments 1 reaction 1 assignee View on GitHub

@tombeckenham is already working on this.

Since Sep 17, 2026.

  • #738 by @tombeckenham — closed without merging
waiting-on: author
Dominant language
TypeScript
Stars
3.1k
Forks
331
Avg merge
1d 22h
Merged PRs (30d)
160

Description

Problem

@tanstack/ai itself is on Zod 4 (^4.2.0), but pins @ag-ui/core@0.0.49 which still depends on zod: ^3.22.4. This pulls Zod 3 into the consumer's type graph as a transitive dep, even when the consumer's app is fully on Zod 4.

This breaks consumers using @hookform/resolvers/zod v5 (or any other library with Zod-3-vs-4 dual overload typings), because TypeScript's overload resolver compares two different zod/v4/core/versions.d.ts files in the same compilation:

  • Zod 3.25.x's v4/core shim: version.minor: 0
  • Zod 4.x: version.minor: 3 (or current)

Producing errors like:

error TS2769: No overload matches this call.
  Overload 2 of 4, '(schema: \$ZodType<...>, ...): Resolver<...>', gave the following error.
    The types of '_zod.version.minor' are incompatible between these types.
      Type '3' is not assignable to type '0'.

Repro

  1. Install @tanstack/ai (any recent version)
  2. Install @hookform/resolvers@5 and zod@^4.3
  3. Run tsc --noEmit on any file calling zodResolver(z.object({...}))

Tracking upstream

The right long-term fix is @ag-ui/core moving to Zod 4 — tracked in ag-ui-protocol/ag-ui#1397 (open, no ETA).

Suggested workarounds for @tanstack/ai

While #1397 is unresolved:

  1. Document the transitive Zod 3 footgun in the @tanstack/ai README / migration notes so consumers know to expect resolver typing breakage.
  2. Vendor or shim @ag-ui/core types internally so zod/v3 doesn't surface in consumer type graphs.
  3. Or just push #1397 to land — @tanstack/ai is the largest downstream consumer of @ag-ui/core and your influence there would help.

Happy to PR #1 if useful.

Local workaround we used

Module declaration override in our app:

// types/hookform-resolvers.d.ts
declare module '@hookform/resolvers/zod' {
  import type { FieldValues, Resolver } from 'react-hook-form';
  export function zodResolver<TInput extends FieldValues, TContext = unknown, TOutput = TInput>(
    schema: { _zod: { output: TOutput; input: TInput } } | { _output: TOutput; _input: TInput; _def: { typeName: string } },
    schemaOptions?: unknown,
    resolverOptions?: { mode?: 'async' | 'sync'; raw?: false },
  ): Resolver<TInput, TContext, TOutput>;
}

Runtime is fine — both Zod 3 and Zod 4 schemas are recognized at runtime by the resolver.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.