fix(upload): answer client-caused chunk states with their own status code
An unknown, finished or expired upload id, and a complete call with chunks missing, were plain Errors with no statusCode, so both routes fell through to the blanket 500 and logged at error level. All four are the client's mistake: they read as a backend fault in monitoring and invite a retry that can never succeed. They now carry 404, 409, 410 and 400 respectively, and both routes pass a tagged status through instead of matching on the two they happened to know about. Only genuinely unexpected errors reach the 500 and the error log. No client is affected: uploadLargeFile, the only caller of this endpoint family, still has no callers of its own. Relates to issue 1403
This commit is contained in:
@@ -222,6 +222,33 @@ describe('chunked upload streams the body under a cap (#1403)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// These were plain Errors, so the routes answered 500 for what are plainly
|
||||
// client mistakes — a backend fault in monitoring, and an invitation to
|
||||
// retry something that can never succeed.
|
||||
describe('client-caused states carry their own status code', () => {
|
||||
it('404s an unknown upload id rather than 500', async () => {
|
||||
await expect(chunkedUpload.uploadChunk('does-not-exist', 0, Buffer.alloc(10)))
|
||||
.rejects.toMatchObject({ statusCode: 404 });
|
||||
});
|
||||
|
||||
// 409 (wrong status) and 410 (expired) share uploadStateError with the two
|
||||
// covered here. Reaching them from the public surface needs either a clock
|
||||
// or a setter the service does not expose, and a test that pretends to
|
||||
// exercise them while actually hitting the 404 path is worse than none.
|
||||
|
||||
it('404s completing an unknown upload rather than 500', async () => {
|
||||
await expect(chunkedUpload.completeUpload('does-not-exist'))
|
||||
.rejects.toMatchObject({ statusCode: 404 });
|
||||
});
|
||||
|
||||
it('400s completing an upload that is missing chunks', async () => {
|
||||
const { uploadId } = await init();
|
||||
await chunkedUpload.uploadChunk(uploadId, 0, Buffer.alloc(10));
|
||||
await expect(chunkedUpload.completeUpload(uploadId))
|
||||
.rejects.toMatchObject({ statusCode: 400 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('the happy path still works', () => {
|
||||
it('writes a streamed chunk and reports progress', async () => {
|
||||
const { uploadId } = await init();
|
||||
|
||||
Reference in New Issue
Block a user