Skip to content

Commit c42018e

Browse files
fix(tables): map row-limit errors to 400 in create-from-CSV import
1 parent 6382f9c commit c42018e

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

apps/sim/app/api/table/import-csv/route.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ vi.mock('@/app/api/table/utils', async () => {
3939
{ error: error.message },
4040
{ status: error.code === 'FILE_TOO_LARGE' ? 413 : 400 }
4141
),
42+
rowWriteErrorResponse: (error: unknown) => {
43+
const message = error instanceof Error ? error.message : String(error)
44+
return message.includes('row limit')
45+
? NextResponse.json({ error: message }, { status: 400 })
46+
: null
47+
},
4248
}
4349
})
4450
vi.mock('@/lib/workspaces/permissions/utils', () => permissionsMock)
@@ -175,6 +181,17 @@ describe('POST /api/table/import-csv', () => {
175181
expect(mockCreateTable).not.toHaveBeenCalled()
176182
})
177183

184+
it('returns 400 with the reason when an insert exceeds the plan row limit', async () => {
185+
mockBatchInsertRows.mockRejectedValueOnce(
186+
new Error('This table has reached its row limit (1,000 rows) on your current plan.')
187+
)
188+
const response = await POST(makeRequest(uploadParts(csvWithRows(250))))
189+
const data = await response.json()
190+
191+
expect(response.status).toBe(400)
192+
expect(data.error).toMatch(/row limit/)
193+
})
194+
178195
it('rolls back the created table when a batch insert fails mid-stream', async () => {
179196
mockBatchInsertRows
180197
.mockResolvedValueOnce(Array.from({ length: 100 }, () => ({ id: 'row' })))

apps/sim/app/api/table/import-csv/route.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
csvProxyBodyCapResponse,
3131
multipartErrorResponse,
3232
normalizeColumn,
33+
rowWriteErrorResponse,
3334
} from '@/app/api/table/utils'
3435

3536
const logger = createLogger('TableImportCSV')
@@ -205,9 +206,13 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
205206
} catch (error) {
206207
if (isMultipartError(error)) return multipartErrorResponse(error)
207208

208-
const message = toError(error).message
209209
logger.error(`[${requestId}] CSV import failed:`, error)
210210

211+
// Row-write failures (e.g. the plan row-limit check) map to a 400 with the real reason.
212+
const rowWriteError = rowWriteErrorResponse(error)
213+
if (rowWriteError) return rowWriteError
214+
215+
const message = toError(error).message
211216
const isClientError =
212217
message.includes('maximum table limit') ||
213218
message.includes('CSV file has no') ||

0 commit comments

Comments
 (0)