fix(http): preserve batch delete client errors

Let status-coded 4xx errors reach the shared Fastify handler so missing sessions remain distinguishable from transaction failures. Add regression coverage for the missing-session response.
This commit is contained in:
digua committed 2026-07-16 20:09:18 +08:00
1 parent c4ad84cb7a
commit 041d2191da
2 files changed
+27 -1

No files matched your search

@@ -388,6 +388,22 @@ describe('registerSharedRoutes smoke tests', () => {
assert.equal(memberCount.count, 2)
})
it('POST /_web/sessions/:id/members/batch-delete preserves missing-session errors', async () => {
const routeApp = Fastify()
registerSharedRoutes(routeApp, createTestContext())
await routeApp.ready()
const resp = await routeApp.inject({
method: 'POST',
url: '/_web/sessions/missing/members/batch-delete',
payload: { memberIds: [1] },
})
await routeApp.close()
assert.equal(resp.statusCode, 404)
})
it('POST /_web/sessions/:id/members/batch-delete rolls back every deletion when one member fails', async () => {
const db = createSessionDb()
db.exec(`
+11 -1
View File
@@ -64,7 +64,7 @@ export function registerMemberRoutes(server: FastifyInstance, ctx: MemberRouteCo
throw new Error('Member deletion transaction returned no result')
}
} catch (error) {
if (apiErrorFromUnknown(error)) throw error
if (apiErrorFromUnknown(error) || isHttpClientError(error)) throw error
appLogger.error('members', 'Batch member deletion failed', error)
return reply.code(500).send({ success: false, error: 'Failed to delete selected members' })
}
@@ -94,3 +94,13 @@ export function registerMemberRoutes(server: FastifyInstance, ctx: MemberRouteCo
}
)
}
function isHttpClientError(error: unknown): error is Error & { statusCode: number } {
return (
error instanceof Error &&
'statusCode' in error &&
typeof error.statusCode === 'number' &&
error.statusCode >= 400 &&
error.statusCode < 500
)
}