Skip to content

Commit 1780a0c

Browse files
authored
fix: JS should return an error if body is empty (#1114)
1 parent cf549f8 commit 1780a0c

3 files changed

Lines changed: 116 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"e2b": patch
3+
---
4+
5+
Fix error handling for API responses with empty body.

packages/js-sdk/src/api/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ export function handleApiError(
1414
) => Error = SandboxError,
1515
stackTrace?: string
1616
): Error | undefined {
17-
if (!response.error) {
17+
// openapi-fetch returns empty string for error when response body is empty,
18+
// so we check !== undefined instead of truthiness
19+
if (response.error === undefined) {
1820
return
1921
}
2022

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { assert, test, describe } from 'vitest'
2+
import { handleApiError } from '../../src/api'
3+
import {
4+
AuthenticationError,
5+
RateLimitError,
6+
SandboxError,
7+
} from '../../src/errors'
8+
9+
function createMockResponse(
10+
status: number,
11+
error: unknown,
12+
data?: unknown
13+
): {
14+
response: { status: number; ok: boolean }
15+
error: unknown
16+
data: unknown
17+
} {
18+
return {
19+
response: { status, ok: status >= 200 && status < 300 },
20+
error,
21+
data,
22+
}
23+
}
24+
25+
describe('handleApiError', () => {
26+
describe('with empty error body', () => {
27+
test('catches 404 with empty string error', () => {
28+
const res = createMockResponse(404, '')
29+
const err = handleApiError(res as any)
30+
assert.instanceOf(err, SandboxError)
31+
assert.include(err?.message, '404')
32+
})
33+
34+
test('catches 400 with empty string error', () => {
35+
const res = createMockResponse(400, '')
36+
const err = handleApiError(res as any)
37+
assert.instanceOf(err, SandboxError)
38+
assert.include(err?.message, '400')
39+
})
40+
41+
test('catches 500 with empty string error', () => {
42+
const res = createMockResponse(500, '')
43+
const err = handleApiError(res as any)
44+
assert.instanceOf(err, SandboxError)
45+
assert.include(err?.message, '500')
46+
})
47+
})
48+
49+
describe('with JSON error body', () => {
50+
test('catches 404 with message', () => {
51+
const res = createMockResponse(404, { code: 404, message: 'Not found' })
52+
const err = handleApiError(res as any)
53+
assert.instanceOf(err, SandboxError)
54+
assert.include(err?.message, 'Not found')
55+
})
56+
57+
test('catches 400 with message', () => {
58+
const res = createMockResponse(400, { code: 400, message: 'Bad request' })
59+
const err = handleApiError(res as any)
60+
assert.instanceOf(err, SandboxError)
61+
assert.include(err?.message, 'Bad request')
62+
})
63+
})
64+
65+
describe('special status codes', () => {
66+
test('returns AuthenticationError for 401', () => {
67+
const res = createMockResponse(401, { message: 'Invalid token' })
68+
const err = handleApiError(res as any)
69+
assert.instanceOf(err, AuthenticationError)
70+
assert.include(err?.message, 'Unauthorized')
71+
})
72+
73+
test('returns AuthenticationError for 401 with empty body', () => {
74+
const res = createMockResponse(401, '')
75+
const err = handleApiError(res as any)
76+
assert.instanceOf(err, AuthenticationError)
77+
assert.include(err?.message, 'Unauthorized')
78+
})
79+
80+
test('returns RateLimitError for 429', () => {
81+
const res = createMockResponse(429, { message: 'Too many requests' })
82+
const err = handleApiError(res as any)
83+
assert.instanceOf(err, RateLimitError)
84+
assert.include(err?.message, 'Rate limit')
85+
})
86+
87+
test('returns RateLimitError for 429 with empty body', () => {
88+
const res = createMockResponse(429, '')
89+
const err = handleApiError(res as any)
90+
assert.instanceOf(err, RateLimitError)
91+
assert.include(err?.message, 'Rate limit')
92+
})
93+
})
94+
95+
describe('success responses', () => {
96+
test('returns undefined for 200 success', () => {
97+
const res = createMockResponse(200, undefined, { id: '123' })
98+
const err = handleApiError(res as any)
99+
assert.isUndefined(err)
100+
})
101+
102+
test('returns undefined for 201 success', () => {
103+
const res = createMockResponse(201, undefined, { id: '123' })
104+
const err = handleApiError(res as any)
105+
assert.isUndefined(err)
106+
})
107+
})
108+
})

0 commit comments

Comments
 (0)