#zCustomQuery type error

1 messages · Page 1 of 1 (latest)

candid shardBOT
#

Hi @inner elm. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The type error you're seeing when using zCustomQuery with zid("tableName") is a known issue related to how Zod and Convex's type system interact, especially around ID validation.

Here's what's happening:

  • The zid("tableName") helper from convex-helpers/server/zod is designed to let you use Zod for argument validation, but it only checks for a string at parse time in the browser. The actual table name validation happens when Convex converts the Zod schema to a Convex validator under the hood, not during Zod's own validation step. This can lead to type mismatches between what Zod expects (a string) and what Convex expects (an Id<"tableName"> branded type) when you use the generated types in your client code or when calling the function from TypeScript code on the client side.

  • The error message you posted:

    Argument of type '{ tableNameId: Id<"tableName">; }' is not assignable to parameter of type '{ [x: string]: undefined; tableNameId: string & { __tableName: "tableName"; }; }'.
    

    indicates that the function expects a value of type string & { __tableName: "tableName"; } (the branded ID type), but you're passing an Id<"tableName">. This is a subtle difference in how the types are constructed and checked.

Workarounds and Recommendations:

  • If you want to use Zod validation with Convex and maintain type safety, you may need to cast your ID to the expected branded type when calling the function from the client, as shown in other support threads:

    useQuery(api.table.getById, {
      tableNameId: tableNameId as Id<"tableName">,
    });
    
#
  • Alternatively, if you want to handle invalid IDs gracefully (e.g., when users can tamper with URL params), you can use a string validator and then manually validate or normalize the ID inside your handler using ctx.db.normalizeId or similar, as suggested in other threads. This gives you more control over error handling and avoids the type mismatch:

    args: { tableNameId: z.string() },
    handler: async (ctx, args) => {
      const id = ctx.db.normalizeId("tableName", args.tableNameId);
      if (!id) throw new Error("Invalid ID");
      // proceed with id
    }
    
  • The Convex team and community have discussed similar issues, and the consensus is that the type mismatch is a result of how Zod and Convex validators are bridged. The zid helper is a convenience, but it doesn't provide full type safety at the Zod level—only at the Convex runtime level. If you need stricter type safety, using Convex's own validators (v.id("tableName")) is more robust, as you've noticed when switching to customQuery and v.id("tableName")zid(tablename) explanation.

Summary:
This is a limitation of the current Zod integration with Convex. For strict type safety, prefer Convex's own validators. If you need to use Zod, be prepared to cast IDs or handle them as strings and validate them at runtime.

If you need more specific guidance or a workaround for your exact use case, please provide a code snippet of how you're calling the query from the client, as the solution may depend on that context.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@inner elm Kapa.ai is still learning and improving, please let me know how I did by reacting below.

inner elm
#

@candid shard my query does type cast, e.g.

const query = await ctx.runQuery(internal.router.file.function, { tableNameId: parsedBody.tableNameId as Id<"tableName">, });

that's where the is incompatible with index signature. error comes up.

candid shardBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

The type error you’re encountering when casting parsedBody.tableNameId as Id<"tableName"> and passing it to a query using zCustomQuery with zid("tableName") is a known friction point between Convex’s branded ID types and Zod-based validation.

What’s happening:

  • The zid("tableName") helper from convex-helpers/server/zod creates a Zod schema that, at runtime, only checks for a string. The actual Convex validator (which expects the branded Id<"tableName"> type) is generated under the hood for server-side validation.
  • However, the generated TypeScript types for the query expect the argument to be of type string & { __tableName: "tableName" }, which is not exactly the same as Id<"tableName"> (even though they are structurally similar).
  • When you cast your value as Id<"tableName"> and pass it to the query, TypeScript sees a mismatch because the index signature expects a more specific branded type, not just any Id<"tableName">.
#

Relevant context from the knowledge sources:

  • This type mismatch is a known issue when using Zod-based helpers with Convex, as discussed in the community and documentation. The Zod validator only ensures the value is a string at parse time, and the Convex runtime does the table name validation. This can lead to type incompatibilities in TypeScript, especially when calling queries from the client or from server code that expects the branded type zid(tablename) explanation.
  • A similar issue is discussed in Discord, where casting to Id<"tableName"> is suggested as a workaround, but it may not always satisfy the stricter type expected by the generated API types, especially when Zod is involved and the types are not perfectly aligned between Zod and Convex’s own validators Discord: TS issue with query argument.

Workarounds:

  • If you control both the client and server, and you are sure the value is a valid ID, you can use a type assertion, but you may still see this error if the types are not exactly compatible.
  • Alternatively, you can define your argument as a plain string in the Zod schema and then use ctx.db.normalizeId("tableName", value) inside your handler to validate and convert it to an ID. This avoids the type mismatch and gives you more control over error handling Discord: Value does not match validator.
#

Summary:
This is a limitation of the current Zod integration with Convex. The type mismatch arises because Zod’s zid helper and Convex’s branded ID types are not perfectly aligned in TypeScript. Using v.id("tableName") with Convex’s own validators avoids this issue, but if you need to use Zod, consider handling IDs as strings and normalizing them at runtime.

If you need stricter type safety and want to avoid these issues, prefer Convex’s built-in validators over Zod for ID fields.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: