PageSourceSearch

https://trpc.io/assets/js/354f7642.56d4410c.js

js trpc.io collected 2026-10-02 02:28:21 UTC 18,046 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkwww=self.webpackChunkwww||[]).push([["36497"],{69286(s,o,l){l.r(o),l.d(o,{metadata:()=>a,default:()=>d,frontMatter:()=>t,contentTitle:()=>p,toc:()=>c,assets:()=>r});var a=JSON.parse('{"id":"client/vanilla/error-handling","title":"Error Handling","description":"A failed procedure call rejects with a TRPCClientError. You can either let it throw and catch it, or use safe() to get it back as a type-safe value.","source":"@site/docs/client/vanilla/error-handling.md","sourceDirName":"client/vanilla","slug":"/client/vanilla/error-handling","permalink":"/docs/client/vanilla/error-handling","draft":false,"unlisted":false,"editUrl":"https://github.com/trpc/trpc/tree/main/www/docs/client/vanilla/error-handling.md","tags":[],"version":"current","frontMatter":{"id":"error-handling","title":"Error Handling","sidebar_label":"Error Handling","slug":"/client/vanilla/error-handling"},"sidebar":"docs","previous":{"title":"Inferring Types","permalink":"/docs/client/vanilla/infer-types"},"next":{"title":"Aborting Procedure Calls","permalink":"/docs/client/vanilla/aborting-procedure-calls"}}'),e=l(27968),n=l(77334);let t={id:"error-handling",title:"Error Handling",sidebar_label:"Error Handling",slug:"/client/vanilla/error-handling"},p,r={},c=[{value:"Catching a thrown error",id:"catching-a-thrown-error",level:2},{value:"Errors as values with <code>safe()</code>",id:"errors-as-values-with-safe",level:2}];function i(s){let o={a:"a",admonition:"admonition",code:"code",div:"div",h2:"h2",p:"p",...(0,n.R)(),...s.components};return(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(o.div,{dangerouslySetInnerHTML:{__html:""}}),"\n",(0,e.jsxs)(o.p,{children:["A failed procedure call rejects with a ",(0,e.jsx)(o.a,{href:"/docs/client/vanilla/infer-types#infer-trpcclienterror-types",children:(0,e.jsx)(o.code,{children:"TRPCClientError"})}),". You can either let it throw and catch it, or use ",(0,e.jsx)(o.code,{children:"safe()"})," to get it back as a type-safe value."]}),"\n",(0,e.jsx)(o.h2,{id:"catching-a-thrown-error",children:"Catching a thrown error"}),"\n",(0,e.jsxs)(o.p,{children:[(0,e.jsx)(o.code,{children:"query()"})," and ",(0,e.jsx)(o.code,{children:"mutate()"})," behave like any other promise, so a ",(0,e.jsx)(o.code,{children:"try"}),"/",(0,e.jsx)(o.code,{children:"catch"})," works as you would expect. TypeScript has no way to describe what a function throws, though, so ",(0,e.jsx)(o.code,{children:"cause"})," arrives as ",(0,e.jsx)(o.code,{children:"unknown"})," and has to be narrowed:"]}),"\n",(0,e.jsx)(o.div,{dangerouslySetInnerHTML:{__html:'<pre class="shiki min-light with-title twoslash lsp" style="background-color: #ffffff; color: #24292eff" title="client.ts"><div class=\'code-title\'>client.ts</div><div class="language-id">ts</div><div class=\'code-container\'><code><div class=\'line\'><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> { TRPCClientError } </span><span style="color: #D32F2F">from</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&apos;@trpc/client&apos;</span><span style="color: #24292EFF">;</span></div><div class=\'line\'><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">type</span><span style="color: #24292EFF"> { AppRouter } </span><span style="color: #D32F2F">from</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&apos;./server&apos;</span><span style="color: #24292EFF">;</span></div><div class=\'line\'><span style="color: #D32F2F">import</span><span style="color: #24292EFF"><data-lsp lsp=\'import z\' ></data-lsp> { trpc } </span><span style="color: #D32F2F">from</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&apos;./trpc&apos;</span><span style="color: #24292EFF">;</span></div><div class=\'line\'>&nbsp;</div><div class=\'line\'><span style="color: #D32F2F">try</span><span style="color: #24292EFF"> {</span></div><div class=\'line\'><span style="color: #24292EFF">  </span><span style="color: #D32F2F">const</span><span style="color: #24292EFF"> </span><span style="color: #1976D2">post</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">await</span><span style="color: #24292EFF"> </span><span style="color: #1976D2">trpc</span><span style="color: #6F42C1">.</span><span style="color: #1976D2">post</span><span style="color: #6F42C1">.</span><span style="color: #1976D2">byId</span><span style="color: #6F42C1">.query</span><span style="color: #24292EFF">(</span><span style="color: #22863A">&apos;1&apos;</span><span style="color: #24292EFF">);</span></div><div class=\'line\'><span style="color: #24292EFF">} </span><span style="color: #D32F2F">catch</span><span style="color: #24292EFF"> (cause) {</span></div><div class=\'line\'><span style="color: #24292EFF">  </span><span style="color: #D32F2F">if</span><span style="color: #24292EFF">
1 (cause </span><span style="color: #D32F2F">instanceof</span><span style="color: #24292EFF"> </span><span style="color: #6F42C1">TRPCClientError</span><span style="color: #24292EFF">) {</span></div><div class=\'line\'><span style="color: #24292EFF">    </span><span style="color: #1976D2">console</span><span style="color: #6F42C1">.log</span><span style="color: #24292EFF">(</span><span style="color: #1976D2">cause</span><span style="color: #24292EFF">.data);</span></div><div class=\'line\'><span style="color: #24292EFF">  } </span><span style="color: #D32F2F">else</span><span style="color: #24292EFF"> {</span></div><div class=\'line\'><span style="color: #24292EFF">    </span><span style="color: #C2C3C5"><data-lsp lsp=\'const t: TRPCRootObject&lt;object, object, RuntimeConfigOptions&lt;object, object>, {&#10;    ctx: object;&#10;    meta: object;&#10;    errorShape: DefaultErrorShape;&#10;    transformer: false;&#10;}>\' ></data-lsp><data-lsp lsp=\'(alias) const initTRPC: TRPCBuilder&lt;object, object>&#10;import initTRPC\' ></data-lsp><data-lsp lsp=\'(method) TRPCBuilder&lt;object, object>.create&lt;RuntimeConfigOptions&lt;object, object>>(opts?: RuntimeConfigOptions&lt;object, object> | undefined): TRPCRootObject&lt;object, object, RuntimeConfigOptions&lt;object, object>, {&#10;    ctx: object;&#10;    meta: object;&#10;    errorShape: DefaultErrorShape;&#10;    transformer: false;&#10;}>\' ></data-lsp>// something that isn&apos;t a tRPC error</span></div><div class=\'line\'><span style="color: #24292EFF">  }</span></div><div class=\'line\'><span style="color: #24292EFF">}</span></div></code></div><button type="button" aria-label="Copy code to clipboard" class="copy-button" onclick="navigator.clipboard.writeText(this.previousSibling.innerText);this.classList.add(\'copied\');this.textContent = \'Copied\';setTimeout(() => {this.classList.remove(\'copied\');this.textContent = \'Copy\'}, 2000)">Copy</button></pre>\n<pre class="shiki github-dark with-title twoslash lsp" style="background-color: #0d1117; color: #c9d1d9" title="client.ts"><div class=\'code-title\'>client.ts</div><div class="language-id">ts</div><div class=\'code-container\'><code><div class=\'line\'><span style="color: #FF7B72">import</span><span style="color: #C9D1D9"> { TRPCClientError } </span><span style="color: #FF7B72">from</span><span style="color: #C9D1D9"> </span><span style="color: #A5D6FF">&apos;@trpc/client&apos;</span><span style="color: #C9D1D9">;</span></div><div class=\'line\'><span style="color: #FF7B72">import</span><span style="color: #C9D1D9"> </span><span style="color: #FF7B72">type</span><span style="color: #C9D1D9"> { AppRouter } </span><span style="color: #FF7B72">from</span><span style="color: #C9D1D9"> </span><span style="color: #A5D6FF">&apos;./server&apos;</span><span style="color: #C9D1D9">;</span></div><div class=\'line\'><span style="color: #FF7B72">import</span><span style="color: #C9D1D9"><data-lsp lsp=\'import z\' ></data-lsp> { trpc } </span><span style="color: #FF7B72">from</span><span style="color: #C9D1D9"> </span><span style="color: #A5D6FF">&apos;./trpc&apos;</span><span style="color: #C9D1D9">;</span></div><div class=\'line\'>&nbsp;</div><div class=\'line\'><span style="color: #FF7B72">try</span><span style="color: #C9D1D9"> {</span></div><div class=\'line\'><span style="color: #C9D1D9">  </span><span style="color: #FF7B72">const</span><span style="color: #C9D1D9"> </span><span style="color: #79C0FF">post</span><span style="color: #C9D1D9"> </span><span style="color: #FF7B72">=</span><span style="color: #C9D1D9"> </span><span style="color: #FF7B72">await</span><span style="color: #C9D1D9"> trpc.post.byId.</span><span style="color: #D2A8FF">query</span><span style="color: #C9D1D9">(</span><span style="color: #A5D6FF">&apos;1&apos;</span><span style="color: #C9D1D9">);</span></div><div class=\'line\'><span style="color: #C9D1D9">} </span><span style="color: #FF7B72">catch</span><span style="color: #C9D1D9"> (cause) {</span></div><div class=\'line\'><span style="color: #C9D1D9">  </span><span style="color: #FF7B72">if</span><span style="color: #C9D1D9">
1 (cause </span><span style="color: #FF7B72">instanceof</span><span style="color: #C9D1D9"> </span><span style="color: #FFA657">TRPCClientError</span><span style="color: #C9D1D9">) {</span></div><div class=\'line\'><span style="color: #C9D1D9">    console.</span><span style="color: #D2A8FF">log</span><span style="color: #C9D1D9">(cause.data);</span></div><div class=\'line\'><span style="color: #C9D1D9">  } </span><span style="color: #FF7B72">else</span><span style="color: #C9D1D9"> {</span></div><div class=\'line\'><span style="color: #C9D1D9">    </span><span style="color: #8B949E"><data-lsp lsp=\'const t: TRPCRootObject&lt;object, object, RuntimeConfigOptions&lt;object, object>, {&#10;    ctx: object;&#10;    meta: object;&#10;    errorShape: DefaultErrorShape;&#10;    transformer: false;&#10;}>\' ></data-lsp><data-lsp lsp=\'(alias) const initTRPC: TRPCBuilder&lt;object, object>&#10;import initTRPC\' ></data-lsp><data-lsp lsp=\'(method) TRPCBuilder&lt;object, object>.create&lt;RuntimeConfigOptions&lt;object, object>>(opts?: RuntimeConfigOptions&lt;object, object> | undefined): TRPCRootObject&lt;object, object, RuntimeConfigOptions&lt;object, object>, {&#10;    ctx: object;&#10;    meta: object;&#10;    errorShape: DefaultErrorShape;&#10;    transformer: false;&#10;}>\' ></data-lsp>// something that isn&apos;t a tRPC error</span></div><div class=\'line\'><span style="color: #C9D1D9">  }</span></div><div class=\'line\'><span style="color: #C9D1D9">}</span></div></code></div><button type="button" aria-label="Copy code to clipboard" class="copy-button" onclick="navigator.clipboard.writeText(this.previousSibling.innerText);this.classList.add(\'copied\');this.textContent = \'Copied\';setTimeout(() => {this.classList.remove(\'copied\');this.textContent = \'Copy\'}, 2000)">Copy</button></pre>'}}),"\n",(0,e.jsxs)(o.p,{children:["See ",(0,e.jsx)(o.a,{href:"/docs/client/vanilla/infer-types#infer-trpcclienterror-types",children:"Inferring Types"})," for a reusable ",(0,e.jsx)(o.code,{children:"isTRPCClientError"})," guard."]}),"\n",(0,e.jsxs)(o.h2,{id:"errors-as-values-with-safe",children:["Errors as values with ",(0,e.jsx)(o.code,{children:"safe()"})]}),"\n",(0,e.jsxs)(o.p,{children:[(0,e.jsx)(o.code,{children:"safe()"})," awaits a ",(0,e.jsx)(o.code,{children:"query()"})," or ",(0,e.jsx)(o.code,{children:"mutate()"})," call without letting it throw, handing back a ",(0,e.jsx)(o.code,{children:"[data, error]"})," pair instead. Exactly one side is ever set, so checking either one narrows the other:"]}),"\n",(0,e.jsx)(o.div,{dangerouslySetInnerHTML:{__html:'<pre class="shiki min-light with-title twoslash lsp" style="background-color: #ffffff; color: #24292eff" title="client.ts"><div class=\'code-title\'>client.ts</div><div class="language-id">ts</div><div class=\'code-container\'><code><div class=\'line\'><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> { safe } </span><span style="color: #D32F2F">from</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&apos;@trpc/client&apos;</span><span style="color: #24292EFF">;</span></div><div class=\'line\'><span style="color: #D32F2F">import</span><span style="color: #24292EFF"> { trpc } </span><span style="color: #D32F2F">from</span><span style="color: #24292EFF"> </span><span style="color: #22863A">&apos;./trpc&apos;</span><span style="color: #24292EFF">;</span></div><div class=\'line\'>&nbsp;</div><div class=\'line\'><span style="color: #D32F2F">const</span><span style="color: #24292EFF"> [</span><span style="color: #1976D2">post</span><span style="color: #212121">,</span><span style="color: #24292EFF"> </span><span style="color: #1976D2">error</span><span style="color: #24292EFF">
1] </span><span style="color: #D32F2F">=</span><span style="color: #24292EFF"> </span><span style="color: #D32F2F">await</span><span style="color: #24292EFF"> </span><span style="color: #6F42C1">safe</span><span style="color: #24292EFF">(</span><span style="color: #1976D2">trpc</span><span style="color: #6F42C1">.</span><span style="color: #1976D2">post</span><span style="color: #6F42C1">.</span><span style="color: #1976D2">byId</span><span style="color: #6F42C1">.query</span><span style="color: #24292EFF">(</span><span style="color: #22863A">&apos;1&apos;</span><span style="color: #24292EFF">));</span></div><div class=\'line\'>&nbsp;</div><div class=\'line\'><span style="color: #D32F2F">if</span><span style="color: #24292EFF"> (error) {</span></div><div class=\'line\'><span style="color: #24292EFF">  </span><span style="color: #1976D2">console</span><span style="color: #6F42C1">.log</span><span style="color: #24292EFF">(</span><span style="color: #1976D2">error</span><span style="color: #24292EFF">.data);</span></div><div class=\'line\'><span style="color: #24292EFF">} </span><span style="color: #D32F2F">else</span><span style="color: #24292EFF"> {</span></div><div class=\'line\'><span style="color: #24292EFF">  </span><span style="color: #1976D2">console</span><span style="color: #6F42C1">.log</span><span style="color: #24292EFF">(</span><span style="color: #1976D2">post</span><span style="color: #24292EFF">.title);</span></div><div class=\'line\'><span style="color: #24292EFF">}</span></div></code></div><button type="button" aria-label="Copy code to clipboard" class="copy-button" onclick="navigator.clipboard.writeText(this.previousSibling.innerText);this.classList.add(\'copied\');this.textContent = \'Copied\';setTimeout(() => {this.classList.remove(\'copied\');this.textContent = \'Copy\'}, 2000)">Copy</button></pre>\n<pre class="shiki github-dark with-title twoslash lsp" style="background-color: #0d1117; color: #c9d1d9" title="client.ts"><div class=\'code-title\'>client.ts</div><div class="language-id">ts</div><div class=\'code-container\'><code><div class=\'line\'><span style="color: #FF7B72">import</span><span style="color: #C9D1D9"> { safe } </span><span style="color: #FF7B72">from</span><span style="color: #C9D1D9"> </span><span style="color: #A5D6FF">&apos;@trpc/client&apos;</span><span style="color: #C9D1D9">;</span></div><div class=\'line\'><span style="color: #FF7B72">import</span><span style="color: #C9D1D9"> { trpc } </span><span style="color: #FF7B72">from</span><span style="color: #C9D1D9"> </span><span style="color: #A5D6FF">&apos;./trpc&apos;</span><span style="color: #C9D1D9">;</span></div><div class=\'line\'>&nbsp;</div><div class=\'line\'><span style="color: #FF7B72">const</span><span style="color: #C9D1D9"> [</span><span style="color: #79C0FF">post</span><span style="color: #C9D1D9">, </span><span style="color: #79C0FF">error</span><span style="color: #C9D1D9">] </span><span style="color: #FF7B72">=</span><span style="color: #C9D1D9"> </span><span style="color: #FF7B72">await</span><span style="color: #C9D1D9"> </span><span style="color: #D2A8FF">safe</span><span style="color: #C9D1D9">(trpc.post.byId.</span><span style="color: #D2A8FF">query</span><span style="color: #C9D1D9">(</span><span style="color: #A5D6FF">&apos;1&apos;</span><span style="color: #C9D1D9">));</span></div><div class=\'line\'>&nbsp;</div><div class=\'line\'><span style="color: #FF7B72">if</span><span style="color: #C9D1D9"> (error) {</span></div><div class=\'line\'><span style="color: #C9D1D9">  console.</span><span style="color: #D2A8FF">log</span><span style="color: #C9D1D9">(error.data);</span></div><div class=\'line\'><span style="color: #C9D1D9">} </span><span style="color: #FF7B72">else</span><span style="color: #C9D1D9"> {</span></div><div class=\'line\'><span style="color: #C9D1D9">  console.</span><span style="color: #D2A8FF">log</span><span style="color: #C9D1D9">(post.title);</span></div><div class=\'line\'><span style="color: #C9D1D9">}</span></div></code></div><button type="button" aria-label="Copy code to clipboard" class="copy-button" onclick="navigator.clipboard.writeText(this.previousSibling.innerText);this.classList.add(\'copied\');this.textContent = \'Copied\';setTimeout(() => {this.classList.remove(\'copied\');this.textContent = \'Copy\'}, 2000)">Copy</button></pre>'}}),"\n",(0,e.jsx)(o.admonition,{type:"info",children:(0,e.jsxs)(o.p,{children:["Subscriptions don't need ",(0,e.jsx)(o.code,{children:"safe()"})," - they never throw at the call site, and report failures through ",(0,e.jsx)(o.code,{children:"onError"}),", which is already typed with the procedure's error shape."]})})]})}function d(s={}){let{wrapper:o}={...(0,n.R)(),...s.components};return o?(0,e.jsx)(o,{...s,children:(0,e.jsx)(i,{...s})}):i(s)}},77334(s,o,l){l.d(o,{R:()=>t,x:()=>p});var a=l(64700);let e={},n=a.createContext(e);function t(s){let o=a.useContext(n);return a.useMemo(function(){return"function"==typeof s?s(o):{...o,...s}},[o,s])}function p(s){let o;return o=s.disableParentContext?"function"==typeof s.components?s.components(e):s.components||e:t(s.components),a.createElement(n.Provider,{value:o},s.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.