enigmare/v2-crawler
1904
1{"id":"stack-76105855","source":"stackoverflow","questionId":76105855,"title":"Send blob (image) from frontend to backend with nextjs and trpc (T3 stack)","tags":["typescript","next.js","zod","trpc","t3"],"text":"Title: Send blob (image) from frontend to backend with nextjs and trpc (T3 stack)\nTags: typescript, next.js, zod, trpc, t3\nSource: Stack Overflow\n\nQuestion:\nI'm trying to send a picture of a leaflet map from the backend to the frontend where i use the **leaflet-simple-map-screenshoter** library for taking the image. This returns a blob which i want to send to the backend so I can save it into a PDF. I am using the T3 stack which uses Next.js with TRPC. I have tried numerous ways to send it, base64, plain Blob, ArrayBuffer and etc. The problem which arises is that the header request when i send it to the backend is either to large or that it just do not transfer the Blob object correctly.\n\nDo anyone have any idea on how i can solve this? Let me know if you want any other information and i will update the post as soon as possible, thanks!\n\nRegards Olav\n\n========================================\n\nTop Answer:\nAt the time of writing this, tRPC doesn't support FormData. There are some experimental methods available, but I couldn't manage to make them work.\n\n### Solution 1: Presigned URL's\n\nUpload the image directly to S3 via a presigned URL provided by a tRPC procedure. When the image has been uploaded, you can call another tRPC procedure to update any records in your database.\n\nThis has the benefit of making the upload faster and reduces the load on your Next.js server, but has the downside that you can't pre-process the image and that if there's an error you may end up with an orphan image in the s3 bucket.\n\n### Solution 2: Use Next.js 13 API routes\n\nSet up a new route in `src/app/api/` to handle file uploads. Note: Keep using tRPC for everything else in the app, and just use these endpoints to upload files.\n\nWith this alternative you can process images and have a better control of the flow, in exchange of more bandwith used.\n\nCheck out this answer where I show how I did it in my project:\n\nPOST multipart/form-data to Serverless Next.js API (running on Vercel / Now.sh)\n\n### Other solutions\n\nYou could try to use the tRPC's experimental FormData features, at your risk.\n\n========================================\n\nCode:\n```text\nFormData\n```\n\n```text\nsrc/app/api/\n```\n\n========================================\n\nComments:\n- Can I use uploadthing to upload arbitrary files? ie .onnx and other custom file types. I played around with uploading onnx before and I wasn't able to get it working. I also didn't see it in the supported file type extensions. github.com/pingdotgg/uploadthing/blob/…\n- Most recently, I set up a new t3 project (no trpc, no auth, no orm) and then copied the uploadthing docs example, to the letter, other than changed imageUploader to blobUploader github.com/currenthandle/uploadthing-test/blob/main/src/app/‌​api/… It works fine with uploading .json files but fails with .onnx files with error: Error: Could not determine type for network_single.onnx, presigned URL generation failed","metadata":{"transformedAt":"2026-08-18T18:33:44.631Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":2,"totalLines":52,"estimatedTokens":740}}2{"id":"stack-78238774","source":"stackoverflow","questionId":78238774,"title":"onSuccess and onError are not working in newest version of React-Query?","tags":["reactjs","next.js","react-query","tanstackreact-query","trpc"],"text":"Title: onSuccess and onError are not working in newest version of React-Query?\nTags: reactjs, next.js, react-query, tanstackreact-query, trpc\nSource: Stack Overflow\n\nQuestion:\nErrors show up in **onSuccess** and **onError** functions. Did some research and turns out these functions are depcrecated in newest version of React-Query.\n\n```\n\"use client\"\n\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { trpc } from '../_trpc/client'\nimport { Loader2 } from 'lucide-react'\n\nconst Page = () => {\n const router = useRouter()\n\n const searchParams = useSearchParams()\n const origin = searchParams.get('origin')\n\n trpc.authCallback.useQuery(undefined, {\n onSuccess: ({ success }) => {\n if (success) {\n // user is synced to db\n router.push(origin ? `/${origin}` : '/dashboard')\n }\n },\n onError: (err) => {\n if (err.data?.code === 'UNAUTHORIZED') {\n router.push('/sign-in')\n }\n },\n retry: true,\n retryDelay: 500,\n })\n\n return (\n \n \n \n \n Setting up your account...\n \n You will be redirected automatically.\n\n \n \n )\n}\n\nexport default Page\n```\n\nTried some to use some answers from similar problems but they were written in a completely different format and didnt work/i didnt know how to apply them. This is from a YT tutorial btw and im completely new to web dev so im pretty lost here. Any workaround to this?\n\n========================================\n\nTop Answer:\n`onSuccess` and `onError` were removed from `useQuery()` from v5. The reasons are explained here.\n\nI'm not familiar with the `trpc.authCallback`, I don't understand why you have no query function but looks like you're using `useQuery()` which is a mistake. **Logging in or creating an account is a mutation, not a query** because you're mutating some data on the back end.\n\nUse `useMutation()` instead of `useQuery()`, it makes more sense and you can still use `onSuccess` and `onError`.\n\n========================================\n\nCode:\n```js\n\"use client\"\n\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { trpc } from '../_trpc/client'\nimport { Loader2 } from 'lucide-react'\n\nconst Page = () => {\n const router = useRouter()\n\n const searchParams = useSearchParams()\n const origin = searchParams.get('origin')\n\n trpc.authCallback.useQuery(undefined, {\n onSuccess: ({ success }) => {\n if (success) {\n // user is synced to db\n router.push(origin ? `/${origin}` : '/dashboard')\n }\n },\n onError: (err) => {\n if (err.data?.code === 'UNAUTHORIZED') {\n router.push('/sign-in')\n }\n },\n retry: true,\n retryDelay: 500,\n })\n\n return (\n <div className='w-full mt-24 flex justify-center'>\n <div className='flex flex-col items-center gap-2'>\n <Loader2 className='h-8 w-8 animate-spin text-zinc-800' />\n <h3 className='font-semibold text-xl'>\n Setting up your account...\n </h3>\n <p>You will be redirected automatically.</p>\n </div>\n </div>\n )\n}\n\nexport default Page\n```\n\n```js\nconst { data, isLoading, error } = trpc.authCallback.useQuery(undefined, {\n retry: true,\n retryDelay: 500,\n })\n\n useEffect(() => {\n if (data) {\n const { success } = data\n if (success) {\n // user is synced to db\n console.log('Data fetched successfully:', data);\n router.push(origin ? `/${origin}` : '/dashboard')\n }\n }\n else if (error) {\n if (error.data?.code === 'UNAUTHORIZED') {\n router.push('/sign-in')\n }\n }\n\n }, [data, origin, router, error]);\n```\n\n```text\nonSuccess\n```\n\n```text\nonError\n```\n\n```text\nuseEffect\n```\n\n```text\nuseEffect\n```\n\n```text\nonSuccess\n```\n\n```text\nonError\n```\n\n```text\nuseQuery()\n```\n\n```text\ntrpc.authCallback\n```\n\n```text\nuseQuery()\n```\n\n```text\nuseMutation()\n```\n\n```text\nuseQuery()\n```\n\n```text\nonSuccess\n```\n\n```text\nonError\n```\n\n========================================\n\nComments:\n- How is useEffect better than a simple callback? What if I want to just logout a user if request fails with 404? I don't care if it's considered antipatern, having an freaking useEffect is a \"better\" pattern?","metadata":{"transformedAt":"2026-08-18T18:33:44.631Z","totalAnswersIncluded":1,"totalCodeBlocksIncluded":15,"totalLines":192,"estimatedTokens":1041}}3{"id":"stack-77489779","source":"stackoverflow","questionId":77489779,"title":"How to catch errors inside tRPC Middleware thrown in tRPC procedures?","tags":["trpc"],"text":"Title: How to catch errors inside tRPC Middleware thrown in tRPC procedures?\nTags: trpc\nSource: Stack Overflow\n\nQuestion:\nI'm working on a tRPC application integrating Google Drive and Spreadsheet APIs. To facilitate this, I've implemented a custom googleProcedure middleware. This middleware injects necessary context into queries or mutations, enabling access to Drive files or Spreadsheets based on the authenticated user.\n\nMy goal is to streamline error handling. Specifically, I want to intercept errors emanating from queries or procedures connected to Google APIs. I aim to avoid the redundancy of catching errors in each individual procedure. However, my current implementation doesn't effectively capture errors within the procedures. Here's the problematic snippet:\n\n```\nconst googleProcedure = protectedProcedure.use(async ({ ctx, next }) => {\n // Initialization of googleClient, sheets, and drive\n\n try {\n return await next({\n ctx: {\n ...ctx,\n sheets,\n drive,\n },\n });\n } catch (err) {\n if (err && err instanceof GaxiosError && err.code == '401') {\n throw new TRPCError({\n code: 'UNAUTHORIZED',\n message: 'Not authenticated with Google',\n });\n }\n throw err;\n }\n});\n\n// Definitions for googleSpreadsheet router...\nexport const spreadsheet = router({\n create: googleProcedure.mutation(async ({ ctx, input }) => {}),\n appendRow: googleProcedure.mutation(async ({ ctx, input }) => {}),\n getAll: googleProcedure.query(async ({ ctx, input }) => {}),\n trash: googleProcedure.mutation(async ({ ctx, input }) => {}),\n});\n```\n\nIn this code, I attempted to catch Google-related 401 errors and rethrow them as a TRPCError with an 'UNAUTHORIZED' code. Unfortunately, this approach doesn't capture errors as expected.\n\nI'm seeking advice on how to effectively catch and handle these errors in the middleware layer, without embedding try-catch blocks in each procedure. Any insights or suggestions would be greatly appreciated!\n\n========================================\n\nCode:\n```js\nconst googleProcedure = protectedProcedure.use(async ({ ctx, next }) => {\n // Initialization of googleClient, sheets, and drive\n\n try {\n return await next({\n ctx: {\n ...ctx,\n sheets,\n drive,\n },\n });\n } catch (err) {\n if (err && err instanceof GaxiosError && err.code == '401') {\n throw new TRPCError({\n code: 'UNAUTHORIZED',\n message: 'Not authenticated with Google',\n });\n }\n throw err;\n }\n});\n\n// Definitions for googleSpreadsheet router...\nexport const spreadsheet = router({\n create: googleProcedure.mutation(async ({ ctx, input }) => {}),\n appendRow: googleProcedure.mutation(async ({ ctx, input }) => {}),\n getAll: googleProcedure.query(async ({ ctx, input }) => {}),\n trash: googleProcedure.mutation(async ({ ctx, input }) => {}),\n});\n```\n\n```js\nconst errorHandlingProcedure = publicProcedure.use(async ({ ctx, next }) => {\n const resp = await next({ ctx });\n\n if (!resp.ok) {\n console.log('middleware intercepted error');\n throw new TRPCError({ code: 'UNAUTHORIZED' });\n }\n\n return resp;\n});\n\nexport const appRouter = router({\n test: errorHandlingProcedure.query(async () => {\n throw new Error('Error from test procedure');\n }),\n});\n```\n\n```js\nimport { GaxiosError } from \"googleapis-common\";\n\nconst googleProcedure = protectedProcedure.use(async ({ ctx, next }) => {\n // Initialization of googleClient, sheets, and drive\n\n const resp = await next({\n ctx: {\n ...ctx,\n sheets,\n drive,\n },\n });\n\n if (!resp.ok && resp.error.cause instanceof GaxiosError && resp.error.cause.code === '401') {\n throw new TRPCError({\n code: 'UNAUTHORIZED',\n message: 'Not authenticated with Google',\n });\n }\n\n return resp;\n});\n```\n\n```text\nnext()\n```\n\n```text\nnext({ ctx })\n```\n\n```text\nok\n```\n\n```text\nerror\n```\n\n```text\nok\n```\n\n```text\nfalse\n```\n\n```text\ntest\n```\n\n```text\nresp.error.cause\n```","metadata":{"transformedAt":"2026-08-18T18:33:44.631Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":11,"totalLines":155,"estimatedTokens":975}}4{"id":"stack-77877384","source":"stackoverflow","questionId":77877384,"title":"tRPC endpoint with a query parameter","tags":["trpc"],"text":"Title: tRPC endpoint with a query parameter\nTags: trpc\nSource: Stack Overflow\n\nQuestion:\nI am learning tRPC and I wanted to test its endpoint in postman. I have this procedure defined:\n\n```\nworldGreeting: publicProcedure.query(async () => {\n return {\n message: \"Hello World!\",\n }\n}),\nwithName: publicProcedure.input(z.string()).query(async ({ ctx, input }) => {\n return {\n message: \"Hello, \" + input,\n }\n}),\n```\n\nFor the first procedure, I can easily test this in postman by calling the endpoint: `http://localhost:4200/api/trpc/greetings.worldGreeting`. However, I am not sure how to call the endpoint for the procedure `withName`.\n\nI only have this but I am stuck on how to pass the data: `http://localhost:4200/api/trpc/greetings.withName?name=Seven`\n\nI think I am missing the whole point of tRPC or something. How do I pass data in the endpoint?\n\n========================================\n\nCode:\n```js\nworldGreeting: publicProcedure.query(async () => {\n return {\n message: \"Hello World!\",\n }\n}),\nwithName: publicProcedure.input(z.string()).query(async ({ ctx, input }) => {\n return {\n message: \"Hello, \" + input,\n }\n}),\n```\n\n```text\nhttp://localhost:4200/api/trpc/greetings.worldGreeting\n```\n\n```text\nwithName\n```\n\n```text\nhttp://localhost:4200/api/trpc/greetings.withName?name=Seven\n```\n\n```text\nhttp://localhost:4200/api/trpc/greetings.withName?batch=1&input={\"0\":{\"json\": \"Seven\"}}\n```\n\n```text\nz.object({id: z.string()})\n```\n\n```text\njson\n```\n\n```text\n{\"id\": \"...\"}\n```","metadata":{"transformedAt":"2026-08-18T18:33:44.631Z","totalAnswersIncluded":0,"totalCodeBlocksIncluded":8,"totalLines":69,"estimatedTokens":376}}5 