Skip to content

Commit f635909

Browse files
authored
fix(server): ensure .actionable throws Next.js errors (#452)
Close #450 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved error handling to ensure specific Next.js navigation errors are re-thrown instead of being handled internally. - **Tests** - Added new tests to verify correct behavior when specific Next.js navigation errors occur. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 0b87474 commit f635909

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

packages/server/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"@orpc/standard-server-node": "workspace:*"
6767
},
6868
"devDependencies": {
69+
"next": "^15.3.0",
6970
"supertest": "^7.1.0"
7071
}
7172
}

packages/server/src/procedure-action.test.ts

+16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ORPCError } from '@orpc/client'
2+
import { forbidden, notFound, redirect, unauthorized } from 'next/navigation'
23
import { createActionableClient } from './procedure-action'
34

45
describe('createActionableClient', () => {
@@ -34,4 +35,19 @@ describe('createActionableClient', () => {
3435
expect(result).toEqual([null, '__mocked__'])
3536
expect(client).toHaveBeenCalledWith('input')
3637
})
38+
39+
it.each([
40+
[() => redirect('/foo')],
41+
[() => forbidden()],
42+
[() => unauthorized()],
43+
[() => notFound()],
44+
])('should rethrow next.js error', async (error) => {
45+
(process as any).env.__NEXT_EXPERIMENTAL_AUTH_INTERRUPTS = true
46+
47+
client.mockImplementationOnce(() => {
48+
error()
49+
})
50+
51+
await expect(action('input')).rejects.toThrowError()
52+
})
3753
})

packages/server/src/procedure-action.ts

+9
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ export function createActionableClient<TInput, TOutput, TError>(
3535
return [null, await client(input)]
3636
}
3737
catch (error) {
38+
if (
39+
error instanceof Error
40+
&& 'digest' in error
41+
&& typeof error.digest === 'string'
42+
&& error.digest.startsWith('NEXT_')
43+
) {
44+
throw error
45+
}
46+
3847
return [toORPCError(error).toJSON(), undefined]
3948
}
4049
}

pnpm-lock.yaml

+11-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)