Sume uploadFile with raw bytes needs a content type, or no request
uploadFile refuses a Uint8Array or ArrayBuffer without contentType and throws SumeUploadError at step create before any call. Pass a typed Blob or a MIME.

If uploadFile from @sume-com/sdk throws contentType is required unless file is a Blob with a type, you passed raw bytes with no MIME type, and nothing was sent. The helper does not guess the type from the filename or from magic bytes. The error is a SumeUploadError with step set to create and status undefined, because no HTTP response exists yet.
Fix it in one of two ways: pass contentType explicitly, or pass a Blob or File whose type is non-empty. A blank or whitespace-only contentType counts as missing, and an explicit value wins over the Blob type.
Which input carries a type
The helper accepts a Blob, an ArrayBuffer or a Uint8Array. Only a Blob can bring its own type. The upload is the first of three calls described in the asset flow: reserve a URL, PUT the bytes, then complete.
| Input | contentType option | Result |
|---|---|---|
| Uint8Array or ArrayBuffer | missing | Throws at step create, no request |
| Uint8Array or ArrayBuffer | image/png | Used as given |
| Blob with type | missing | Blob type used |
| Blob with empty type | missing | Throws at step create, no request |
| Blob with type | video/mp4 | Option wins |
Seeing the guard fire
This script needs no network. The client is built with a placeholder key because the guard throws before the client is used, so you can run it in a unit test.
import { createSumeClient, uploadFile, SumeUploadError } from "@sume-com/sdk";
const client = createSumeClient({ apiKey: "test-key" });
const bytes = new Uint8Array([137, 80, 78, 71]);
try {
await uploadFile({ client, file: bytes });
} catch (error) {
if (error instanceof SumeUploadError) {
console.log(error.step, error.status, error.message);
} else {
throw error;
}
}
// With a type the call proceeds to the network, so pass a real key to run it.
// await uploadFile({ client, file: bytes, contentType: "image/png" });What to do in an upload service
- Take the MIME type from the user-facing upload, such as the multipart part header, and pass it through. Validate it against an allowlist first.
- Do not retry a step create failure with the same arguments. It is deterministic.
- Branch on
error.stepin logs so a missing type is not confused with a storage failure at put. - Check the returned
content_typeagainst what you sent when the type matters downstream.
Related posts
More in Developers
- Sume webhook handler status codes: when to return 401, 2xx or 5xx
Sume retries any non-2xx up to 10 times, 30 seconds apart. Return 2xx only after you store the event. A Python handler that refuses a bad signature.
- Sume job webhooks: failed and canceled both say ERROR, branch on event
job.failed and job.canceled webhook payloads both use status ERROR with an error object. Dispatch on the event name, not status, in Python.
- Sume webhook 300-second tolerance: verify on receipt, not later
A queued Sume webhook fails the 300-second timestamp check if verified late. Verify at the edge, then queue the body. Python with a testable clock.
- Patching Supabase Postgres 17.11 vs Sume's 10-attempt webhook budget
Supabase's September 25 Postgres 15.19 and 17.11 releases fix 44 CVEs. A restart can outlast Sume's ten 30-second webhook attempts, so plan a redeliver.
Written by Sume