Skip to content

Commit e5ae816

Browse files
committed
Suppress handled API client errors
1 parent 3cb28e1 commit e5ae816

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

‎src/app/api/core/utils/withErrorHandler.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export const withErrorHandler = (handler: RequestHandler): RequestHandler => {
3737
if (error instanceof ZodError) {
3838
formattedError = error.format() as ZodFormattedError<string>
3939
}
40-
console.error(formattedError)
4140

4241
// Default staus and message for JSON error response
4342
let status: number = (error as StatusableError).status || httpStatus.BAD_REQUEST
@@ -65,6 +64,10 @@ export const withErrorHandler = (handler: RequestHandler): RequestHandler => {
6564
}
6665
}
6766

67+
if (status >= httpStatus.INTERNAL_SERVER_ERROR) {
68+
console.error(formattedError)
69+
}
70+
6871
return NextResponse.json({ error: message, errors }, { status })
6972
}
7073
}

‎src/app/api/tests/utils/withErrorHandler.test.ts‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@ jest.mock('@/utils/CopilotAPI', () => ({
1313

1414
describe('withErrorHandler util', () => {
1515
let req: NextRequest
16+
let consoleErrorSpy: jest.SpyInstance
1617

1718
beforeEach(() => {
1819
jest.clearAllMocks()
20+
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => undefined)
1921
req = buildNextRequest(`/?token=iu-token`)
2022
})
2123

24+
afterEach(() => {
25+
consoleErrorSpy.mockRestore()
26+
})
27+
2228
it('catches and builds proper response for APIError', async () => {
2329
const handler = async (_req: NextRequest, _params: any) => {
2430
throw new APIError(httpStatus.UNAUTHORIZED, 'Please provide a valid token')
@@ -28,6 +34,7 @@ describe('withErrorHandler util', () => {
2834
const response = await nextResponse.json()
2935
expect(response.error).toBe('Please provide a valid token')
3036
expect(nextResponse.status).toBe(httpStatus.UNAUTHORIZED)
37+
expect(consoleErrorSpy).not.toHaveBeenCalled()
3138
})
3239

3340
it('catches and builds proper response for ZodError', async () => {
@@ -41,6 +48,7 @@ describe('withErrorHandler util', () => {
4148
expect(response.error[0].expected).toBe('string')
4249
expect(response.error[0].received).toBe('number')
4350
expect(nextResponse.status).toBe(httpStatus.UNPROCESSABLE_ENTITY)
51+
expect(consoleErrorSpy).not.toHaveBeenCalled()
4452
})
4553

4654
it('catches and builds proper response for CopilotApiError', async () => {
@@ -52,6 +60,40 @@ describe('withErrorHandler util', () => {
5260
const response = await nextResponse.json()
5361
expect(response.error).toBe('Please provide a valid token')
5462
expect(nextResponse.status).toBe(httpStatus.UNAUTHORIZED)
63+
expect(consoleErrorSpy).not.toHaveBeenCalled()
64+
})
65+
66+
it('catches and builds proper response for Copilot SDK style ApiError', async () => {
67+
const error = new Error('Not Found') as Error & {
68+
status: number
69+
body: { message: string }
70+
}
71+
error.name = 'ApiError'
72+
error.status = httpStatus.NOT_FOUND
73+
error.body = { message: 'Not Found' }
74+
75+
const handler = async (_req: NextRequest, _params: any) => {
76+
throw error
77+
}
78+
79+
const nextResponse = await withErrorHandler(handler)(req, null)
80+
const response = await nextResponse.json()
81+
expect(response.error).toBe('Not Found')
82+
expect(nextResponse.status).toBe(httpStatus.NOT_FOUND)
83+
expect(consoleErrorSpy).not.toHaveBeenCalled()
84+
})
85+
86+
it('logs server errors while returning the standardized response', async () => {
87+
const error = new APIError(httpStatus.INTERNAL_SERVER_ERROR, 'Unexpected failure')
88+
const handler = async (_req: NextRequest, _params: any) => {
89+
throw error
90+
}
91+
92+
const nextResponse = await withErrorHandler(handler)(req, null)
93+
const response = await nextResponse.json()
94+
expect(response.error).toBe('Unexpected failure')
95+
expect(nextResponse.status).toBe(httpStatus.INTERNAL_SERVER_ERROR)
96+
expect(consoleErrorSpy).toHaveBeenCalledWith(error)
5597
})
5698

5799
it('returns proper response if no errors are encountered', async () => {
@@ -63,5 +105,6 @@ describe('withErrorHandler util', () => {
63105
const response = await nextResponse.json()
64106
expect(response.message).toBe('Yay!')
65107
expect(nextResponse.status).toBe(httpStatus.OK)
108+
expect(consoleErrorSpy).not.toHaveBeenCalled()
66109
})
67110
})

0 commit comments

Comments
 (0)