\n\n### Additional information\n\n_No response_\n\n### π¨βπ§βπ¦ Contributing\n\n- [ ] πββοΈ Yes, I'd be down to file a PR fixing this bug!",[3187],{"name":3188,"color":3189},"π bug: unconfirmed","e99695",6924,"bug: wrong types in the new trpc react-query client","2025-09-03T09:28:51Z","https://github.com/trpc/trpc/issues/6924",0.6968704,{"description":3196,"labels":3197,"number":3199,"owner":3178,"repository":3178,"state":3179,"title":3200,"updated_at":3201,"url":3202,"score":3203},"### Provide environment information\n\nnothing\n\n### Describe the bug\n\n\n\n### β Problem\n\nUsing `trpc.studio.getMany.useSuspenseInfiniteQuery({ limit: 5 })` works correctly **on first render**, but after a mutation followed by `utils.studio.getMany.invalidate()`, tRPC triggers a refetch that causes a **400 Bad Request** error.\n\n---\n\n### π Logs\n\n```\nGET /api/trpc/studio.getMany?batch=1&input=%7B%220%22%3A%7B%22limit%22%3A5%2C%22direction%22%3A%22forward%22%7D%7D 400\n```\n\nDecoded input:\n\n```json\n{\n \"0\": {\n \"limit\": 5,\n \"direction\": \"forward\"\n }\n}\n```\n\nExpected input:\n\n```ts\n{\n limit: number;\n direction?: \"forward\" | \"backward\";\n cursor?: {\n id: string;\n updateAt: Date;\n } | null;\n}\n```\n\n---\n\n### β
Steps to Reproduce\n\n1. Use `useSuspenseInfiniteQuery({ limit: 5 })` on the client\n2. Set up schema like:\n\n ```ts\n .input(z.object({\n limit: z.number(),\n cursor: z.object({\n id: z.string().uuid(),\n updateAt: z.coerce.date()\n }).optional().nullable(),\n direction: z.enum([\"forward\", \"backward\"]).optional(),\n }))\n ```\n3. Trigger a mutation\n4. Call `utils.studio.getMany.invalidate()`\n5. Observe 400 error\n\n---\n\n### β
Expected Behavior\n\n* `invalidate()` should **refetch the query** without producing a Zod validation error.\n* `cursor: undefined` and `direction: \"forward\"` should be supported by default, as they are **internally used by `useInfiniteQuery()`**.\n\n---\n\n### π§ Additional Notes\n\n* This issue occurs because React Query internally passes `cursor: undefined` even if the user doesnβt specify it.\n* Only `.optional().nullable()` allows this without throwing a Zod error.\n\n---\n\n### π οΈ Workaround\n\nUpdating the schema like this resolves the issue:\n\n```ts\ncursor: z.object({\n id: z.string().uuid(),\n updateAt: z.coerce.date(),\n}).optional().nullable()\n```\n\n\n\n### Link to reproduction\n\nhttps://github.com/devlopermitesh/Youtube\n\n### To reproduce\n\n\n## π Bug\n\n```bash\ngit clone '\u003Crepo>'\n```\n\nThen click on the `Create` button β\nβ
I see:\n`POST /api/trpc/video.create?batch=1`\n\nBut immediately after:\nβ I get an error:\n`GET /api/trpc/studio.getMany?batch=1&input=%7B%220%22%3A%7B%22limit%22%3A5%2C%22direction%22%3A%22forward%22%7D%7D` β 400 Bad Request\n\n\n\n### Additional information\n\n_No response_\n\n### π¨βπ§βπ¦ Contributing\n\n- [ ] πββοΈ Yes, I'd be down to file a PR fixing this bug!",[3198],{"name":3188,"color":3189},6862,"Bug: useInfiniteQuery causes 400 Bad Request after .invalidate() due to auto-injected cursor: undefined","2025-07-16T11:44:32Z","https://github.com/trpc/trpc/issues/6862",0.7006551,{"description":3205,"labels":3206,"number":3207,"owner":3178,"repository":3208,"state":3179,"title":3209,"updated_at":3210,"url":3211,"score":3212},"heres' an example: \r\n\r\n\u003Cimg width=\"726\" alt=\"image\" src=\"https://github.com/jlalmes/trpc-openapi/assets/4019054/3ff97ec5-7533-4327-9cab-ef683b66390c\">\r\n\r\nif I have this code defining a schema and try to make TRPC calls (on ANY API, not just this one), I'll get this error: \r\n\r\n```\r\nerror - TRPCError: [query.question.read] - Input parser key: \"labels\" must be ZodString, ZodNumber, ZodBoolean, ZodBigInt or ZodDate\r\n at /Users/david/Projects/WORK/DFDF/DDQ360/node_modules/trpc-openapi/dist/generator/schema.js:72:27\r\n at Array.map (\u003Canonymous>)\r\n at getParameterObjects (/Users/david/Projects/WORK/DFDF/DDQ360/node_modules/trpc-openapi/dist/generator/schema.js:65:10)\r\n at /Users/david/Projects/WORK/DFDF/DDQ360/node_modules/trpc-openapi/dist/generator/paths.js:61:66\r\n at forEachOpenApiProcedure (/Users/david/Projects/WORK/DFDF/DDQ360/node_modules/trpc-openapi/dist/utils/procedure.js:34:13)\r\n at getOpenApiPathsObject (/Users/david/Projects/WORK/DFDF/DDQ360/node_modules/trpc-openapi/dist/generator/paths.js:13:45)\r\n at generateOpenApiDocument (/Users/david/Projects/WORK/DFDF/DDQ360/node_modules/trpc-openapi/dist/generator/index.js:27:50)\r\n at eval (webpack-internal:///(api)/./src/server/api/root.ts:51:98)\r\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {\r\n code: 'INTERNAL_SERVER_ERROR',\r\n [cause]: undefined\r\n}\r\n```\r\n\r\n",[],391,"trpc-openapi","zod array objects break this","2024-08-30T17:17:14Z","https://github.com/trpc/trpc-openapi/issues/391",0.70323485,{"description":3214,"labels":3215,"number":3216,"owner":3178,"repository":3178,"state":3217,"title":3218,"updated_at":3219,"url":3220,"score":3221},"Welcome back @KATT, I hope you enjoyed your holidays π\r\n\r\nThe [`invalidateQueries`](https://trpc.io/docs/invalidateQueries) docs say:\r\n\r\n> [See react-query docs](https://react-query.tanstack.com/guides/query-invalidation) if you want more fine-grained control.\r\n\r\nIn turn, the react query docs say:\r\n\r\n- `invalidateQueries()` will invalidate every query (I found this on some other page)\r\n- `invalidateQueries('todos')` will invalidate every query with a key that starts with `'todos'`\r\n- `invalidateQueries({ predicate: query => boolean })` allows fine-grain control\r\n\r\nHowever, if you now try the following with trpc:\r\n\r\n```ts\r\nimport { trpc } from '../utils/trpc'\r\n\r\nconst context = trpc.useContext()\r\n\r\n// Invalid\r\ncontext.invalidateQueries()\r\n\r\n// Works differently than expected:\r\n// Will invalidate the exact query 'todos'\r\n// Will not clear queries that start with 'todos'!\r\ncontext.invalidateQueries('todos') \r\n\r\n// Invalid\r\ncontext.invalidateQueries({ predicate: () => true })\r\n\r\nconst { queryClient } = context\r\n\r\n// Doesn't seem to work for me. Does nothing.\r\nqueryClient.invalidateQueries('todos')\r\n\r\n// Will invalidate the exact query 'todos', if it has no params\r\nqueryClient.invalidateQueries(['todos'])\r\n```\r\n\r\nIf we want to invalidate all queries it must be done as so:\r\n\r\n```ts\r\nqueryClient.invalidateQueries()\r\n```\r\n\r\nIf we want to invalidate queries that start with `'todos'` it must be done like so:\r\n\r\n```ts\r\nqueryClient.invalidateQueries({\r\n predicate({ queryKey }) {\r\n const name = queryKey[0]\r\n return typeof name === 'string' && name.startsWith('todos')\r\n },\r\n})\r\n```\r\n\r\nFor example, when a user logs off in my application, I clear all private queries like so:\r\n\r\n```ts\r\nqueryClient.removeQueries({\r\n predicate({ queryKey }) {\r\n const name = queryKey[0]\r\n return typeof name !== 'string' || !name.includes('public')\r\n },\r\n})\r\n```\r\n\r\nSolutions I propose:\r\n\r\n1. The distinction should be made in the docs that trpc uses arrays as keys, not strings, and thus `invalidateQueries` can't be used in certain ways.\r\n\r\n2. The typing of `invalidateQueries` needs to be fixed (at least) to allow empty args and `{ predicate: (query) => boolean }`.\r\n\r\n3. Maybe there should be a separate `invalidateQueries` / `removeQueries` methods returned directly from `createReactQueryHooks` that allow others to implement query invalidation in a way that makes better sense with trpc. If the typings of `invalidateQueries` are completely fixed, this change would not be necessary. Looking for feedback on whether anyone else thinks this is a good idea.\r\n\r\n ```ts\r\n // Maybe something like this\r\n import { trpc } from '../utils/trpc'\r\n \r\n // Will correctly invalidate every query with a key that starts with `'todos'`\r\n trpc.invalidateQueries(['todos'])\r\n\r\n // Clear all non-public queries\r\n trpc.removeQueries({\r\n predicate([key, params]) {\r\n return !key.includes('public')\r\n },\r\n })\r\n ```",[],1383,"closed","`invalidateQueries` does not work as expected","2022-10-04T18:07:34Z","https://github.com/trpc/trpc/issues/1383",0.6268911,{"description":3223,"labels":3224,"number":3225,"owner":3178,"repository":3178,"state":3217,"title":3226,"updated_at":3227,"url":3228,"score":3229},"### Describe the feature you'd like to request\r\n\r\n### Context\r\nI'm trying to invalidate a query based on some complex rules, as I don't want to invalidate every single call to that query.\r\nThe way to do this is using `.invalidate(undefined, {predicate: (query) })`, where predicate takes a function that dictates which queries should be invalidated.\r\nThe problem I have, is that the `query` has the default `react-query` type of `Query\u003Cunknown,unknown,unknown, unknown[]>` which is not true for our TRPC queries.\r\n\r\n### Demonstration\r\n``` typescript\r\nconst utils = trpc.useContext()\r\nutils.router.query.invalidate(undefined, {\r\n predicate: (query: Query\u003Cunknown,unknown,unknown, unknown[]>) => {\r\n // We will have to cast `query` here to perform the invalidation based on the input data\r\n return true\r\n }\r\n})\r\n```\r\n\r\n### Describe the solution you'd like to see\r\n\r\nWe know that if `invalidate()` is called on a query defined by the user, the typing will be:\r\n``` typescript\r\ntype RouterInput= inferRouterInputs\u003CAppRouter>\r\ntype RouterOutput = inferRouterOutputs\u003CAppRouter>\r\n\r\n// desired type of example query called with `trpc.router.fn` , in predicate invalidation\r\ntype DesiredType = Query\u003C\r\n RouterInput['router']['fn'],\r\n TRPCClientError\u003CAppRouter>,\r\n RouterOutput['router']['fn'],\r\n [ [['router],['fn']], { input: RouterInput10['router']['fn'] } ]\r\n>\r\n```\r\n\r\nIf `invalidate()` is called at a router level, the type of the query, should be a union amongst the posible `DesiredType`'s of the procedures/routers inside it.\r\n\r\n\r\n\r\n### Describe alternate solutions\r\n\r\nCurrently, I implemented a worse version of this to cast the type of the query, but its bad since it only supports queries and only exactly two levels for the path:\r\n\r\n``` typescript\r\ntype QueryHelper\u003C\r\n RouterOutput,\r\n K extends keyof RouterOutput & keyof RouterInput,\r\n K2 extends keyof RouterOutput[K] & keyof RouterInput[K],\r\n > = Query\u003C\r\n RouterInput[K][K2],\r\n TRPCClientError\u003CAppRouter>,\r\n RouterOutput[K][K2],\r\n [K, { input: RouterInput[K][K2] }]\r\n >\r\n\r\nutils.router.query.invalidate(undefined, {\r\n predicate: (_query) => {\r\n const query = _query as unknown as QueryHelper\u003CRouterOutput10, 'router', 'query'>\r\n return false\r\n }\r\n})\r\n```\r\n\r\n### Additional information\r\n\r\n_No response_\r\n\r\n### π¨βπ§βπ¦ Contributing\r\n\r\n- [x] πββοΈ Yes, I'd be down to file a PR implementing this feature!",[],3545,"feat: Stronger typing for predicate invalidation","2023-03-12T18:02:06Z","https://github.com/trpc/trpc/issues/3545",0.63285905,{"description":3231,"labels":3232,"number":104,"owner":3178,"repository":3236,"state":3217,"title":3237,"updated_at":3238,"url":3239,"score":3240},"Current running proposal from me:\r\n\r\n\r\n\r\n### Option A) - Tuples\r\n\r\n**Given a procedure like**\r\n\r\n```ts\r\nt.router({\r\n post: t.router({\r\n byId: t.procedure\r\n .input(z.object({ id: z.string }))\r\n .query(() => '...' )\r\n})\r\n```\r\n\r\n**We can do:**\r\n\r\n```ts\r\n// invalidate the whole \"post router\"\r\nutils.invalidateQueries(['post']);\r\n// Invalidate all `post.byId`-queries\r\nutils.invalidateQueries(['post', 'byId']);\r\n// invalidate specific post\r\nutils.invalidateQueries(['post', 'byId', { id: \"1\" });\r\n```\r\n\r\n### Option B) String literals\r\n\r\nHow it works today, no ability to invalidate a full router without importing react-query and do it in a \"type-unsafe\" manner\r\n\r\n\r\n### π₯ Option C) `Proxy`! Current winning proposal.\r\n\r\nIdea by @sachinraja \r\n\r\n\r\n```ts\r\nfunction MyComponent() {\r\n // a proxy-based context helper?\r\n const utils = proxy.useContext()\r\n\r\n return \u003Cbutton onClick={() => utils.post.byId.invalidate(/* optional input */) } />\r\n}\r\n\r\n```",[3233],{"name":3234,"color":3235},"question","d876e3","examples-v10-next-prisma-starter-sqlite","[RFC] `invalidateQueries` and other `react-query` `useContext()`-fns","2022-08-25T23:31:17Z","https://github.com/trpc/examples-v10-next-prisma-starter-sqlite/issues/3",0.6349936,{"description":3242,"labels":3243,"number":104,"owner":3178,"repository":3244,"state":3217,"title":3245,"updated_at":3246,"url":3247,"score":3240},"Just dumping some thoughts / half-baked ideas here\r\n\r\n\r\n\r\n\r\n- ~~With RSC - is there a point of tRPC? Is there a \"lighter\" approach that might be nice(r)?~~ Maybe, but not for all\r\n- ~~With RSC - is there a point of react-query?~~ yes, there's still client components\r\n- Will there be a way to sync state and make sync the underlying state of the queries from RSC -> client & make *isomorphic* components?\r\n - Biggest question - unsure how state sync can work from a root `\"use client\"` Provider that renders on the server to the client that uses it.\r\n- Will importing the full router on every RSC-request add any significant overhead?\r\n- ~~Will React Context providers be available on the server? If so, it be possible to do any \"isomorphic\" context providers? Will components be able to be isomorphic?~~ This was a misconception. We'll do a root `\"use client\"` component & likely not sync state from actual RSC-components to client\r\n - If query state could be synced from server to client and context providers + components could be isomorphic, we could do stuff like using optimistic updates of a component that was initially rendered on the server.\r\n- How to deal with caching? \r\n- [..]",[],"next-13","Open questions","2022-11-28T10:46:18Z","https://github.com/trpc/next-13/issues/3",{"description":3249,"labels":3250,"number":3251,"owner":3178,"repository":3178,"state":3217,"title":3252,"updated_at":3253,"url":3254,"score":3255},"Let's say I have an API that lists dogs and an API that gets an individual dog. If I delete a dog, I'd like to be able to just do something like:\r\n```typescript\r\nconst utils = trpc.useContext();\r\nutils.invalidateQueries(\"dogs.*\")\r\n```\r\n\r\nCurrently I have to do:\r\n```typescript\r\nconst utils = trpc.useContext();\r\nutils.invalidateQueries([\"dogs.getDog\", { id:\"dog-id\" }])\r\nutils.invalidateQueries([\"dogs.listDogs\"])\r\n```\r\n\r\nUsing vanilla Express and react-query, I'm able to do something like this:\r\n```typescript\r\nconst { data: allDogs } = useQuery([\"dogs\"], /* query definition*/)\r\nconst { data: aDog } = useQuery([\"dogs\", { id: \"dog-id\" }], /* query definition*/)\r\n\r\nconst utils = trpc.useContext();\r\nutils.invalidateQueries([\"dogs\"])\r\n```\r\n\r\nBut with since tRPC structures the query keys for you, I'm not able to.",[],2098,"Support invalidating multiple router queries in one go","2022-07-06T04:22:16Z","https://github.com/trpc/trpc/issues/2098",0.64142203,{"description":3257,"labels":3258,"number":3262,"owner":3178,"repository":3178,"state":3217,"title":3263,"updated_at":3264,"url":3265,"score":3266},"### Provide environment information\n\n```\r\n System:\r\n OS: macOS 12.5.1\r\n CPU: (8) arm64 Apple M1 Pro\r\n Memory: 77.77 MB / 32.00 GB\r\n Shell: 5.8.1 - /bin/zsh\r\n Binaries:\r\n Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node\r\n Yarn: 1.22.19 - ~/.nvm/versions/node/v16.13.0/bin/yarn\r\n npm: 8.1.0 - ~/.nvm/versions/node/v16.13.0/bin/npm\r\n Browsers:\r\n Brave Browser: 108.1.46.144\r\n Chrome: 108.0.5359.124\r\n Firefox Developer Edition: 108.0\r\n Safari: 15.6.1\r\n npmPackages:\r\n @tanstack/react-query: 4.20.4 => 4.20.4 \r\n @trpc/client: 10.6.0 => 10.6.0 \r\n @trpc/react-query: 10.6.0 => 10.6.0 \r\n @trpc/server: 10.6.0 => 10.6.0 \r\n next: 12.3.0 => 12.3.0 \r\n react: 17.0.2 => 17.0.2 \r\n```\n\n### Describe the bug\n\ngiven that you have an environment where you're mixing `useQuery` from `react-query` and queries from `trpc`, `utils.invalidate()` _used to_ target all queries, but now, it only targets the queries created by trpc.\n\n### Link to reproduction\n\nhttps://codesandbox.io/s/festive-newton-rodx1p?file=/src/pages/index.tsx\n\n### To reproduce\n\n- click the `invalidate` button\r\n- observe that only the query created by trpc is invalidated\n\n### Additional information\n\nThis used to work with `10.0.0-rc.3`\r\n\r\nfrom discord:\r\n\r\n```\r\nquick question: I think the change of query keys (that we now have { type: 'query'} etc. at the end) kind of introduced an issue when using trpc together with \"raw\" react-query queries. For reference, we are gradually upgrading to tprc and still have some \"untyped\" useQuery calls lying around.\r\n\r\nOur issue is that we call utils.invalidate() to invalidate all queries in some cases. It used to target all trpc and react-query queries, but now, it only targets the trpc queries. I've debugged into the queryClient and what we get into the invalidation as a key is [[],{}] and this does match \"all trpc queries\", but not \"all queries\".\r\n\r\nOur workaround is to use the real queryClient for invalidation now, just wanted to let you know about that - maybe it just worked coincidentally before\r\n```\n\n### π¨βπ§βπ¦ Contributing\n\n- [ ] πββοΈ Yes, I'd be down to file a PR fixing this bug!",[3259],{"name":3260,"color":3261},"π bug","d73a4a",3456,"bug: query invalidation can only target trpc queries","2023-01-06T12:02:03Z","https://github.com/trpc/trpc/issues/3456",0.6500112,["Reactive",3268],{},["Set"],["ShallowReactive",3271],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fdDo-qW_MlhM45Wvhcx3YNRr1sVHS_rJV6vOrzS9LWxg":-1},"/trpc/trpc/3648"]