Skip to content

Commit dc7833c

Browse files
authored
Catch errors when trying to unwrap responses (#11061)
1 parent 7a5c0a7 commit dc7833c

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

.changeset/catch-unwrap-error.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/router": patch
3+
---
4+
5+
Catch and bubble errors thrown when trying to unwrap responses from `loader`/`action` functions

packages/router/__tests__/navigation-test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,75 @@ describe("navigations", () => {
124124
});
125125
});
126126

127+
it("handles errors when unwrapping Responses", async () => {
128+
let t = setup({
129+
routes: [
130+
{
131+
path: "/",
132+
children: [
133+
{
134+
id: "foo",
135+
path: "foo",
136+
hasErrorBoundary: true,
137+
loader: true,
138+
},
139+
],
140+
},
141+
],
142+
});
143+
let A = await t.navigate("/foo");
144+
await A.loaders.foo.resolve(
145+
// Invalid JSON
146+
new Response('{"key":"value"}}}}}', {
147+
status: 200,
148+
headers: {
149+
"Content-Type": "application/json",
150+
},
151+
})
152+
);
153+
expect(t.router.state.loaderData).toEqual({});
154+
expect(t.router.state.errors).toMatchInlineSnapshot(`
155+
{
156+
"foo": [SyntaxError: Unexpected token } in JSON at position 15],
157+
}
158+
`);
159+
});
160+
161+
it("bubbles errors when unwrapping Responses", async () => {
162+
let t = setup({
163+
routes: [
164+
{
165+
id: "root",
166+
path: "/",
167+
hasErrorBoundary: true,
168+
children: [
169+
{
170+
id: "foo",
171+
path: "foo",
172+
loader: true,
173+
},
174+
],
175+
},
176+
],
177+
});
178+
let A = await t.navigate("/foo");
179+
await A.loaders.foo.resolve(
180+
// Invalid JSON
181+
new Response('{"key":"value"}}}}}', {
182+
status: 200,
183+
headers: {
184+
"Content-Type": "application/json",
185+
},
186+
})
187+
);
188+
expect(t.router.state.loaderData).toEqual({});
189+
expect(t.router.state.errors).toMatchInlineSnapshot(`
190+
{
191+
"root": [SyntaxError: Unexpected token } in JSON at position 15],
192+
}
193+
`);
194+
});
195+
127196
it("does not fetch unchanging layout data", async () => {
128197
let t = initializeTest();
129198
let A = await t.navigate("/foo");

packages/router/router.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3990,13 +3990,18 @@ async function callLoaderOrAction(
39903990
}
39913991

39923992
let data: any;
3993-
let contentType = result.headers.get("Content-Type");
3994-
// Check between word boundaries instead of startsWith() due to the last
3995-
// paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
3996-
if (contentType && /\bapplication\/json\b/.test(contentType)) {
3997-
data = await result.json();
3998-
} else {
3999-
data = await result.text();
3993+
3994+
try {
3995+
let contentType = result.headers.get("Content-Type");
3996+
// Check between word boundaries instead of startsWith() due to the last
3997+
// paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
3998+
if (contentType && /\bapplication\/json\b/.test(contentType)) {
3999+
data = await result.json();
4000+
} else {
4001+
data = await result.text();
4002+
}
4003+
} catch (e) {
4004+
return { type: ResultType.error, error: e };
40004005
}
40014006

40024007
if (resultType === ResultType.error) {

0 commit comments

Comments
 (0)