sveltejs/kit · error · SvelteKitError
Could not deserialize binary form: invalid file offset table
Error message
Could not deserialize binary form: invalid file offset table
What it means
The file offset table read from a binary form payload must be a JSON array of non-negative integers. deserialize_binary_form throws this when the table parses but fails that shape check. This guards against malformed or tampered payloads that would otherwise cause arbitrary file slicing later.
Solutions
- Ensure client and server run the same @sveltejs/kit version so the binary format matches.
- Submit the form through SvelteKit's normal flow (native POST or use:enhance) so serialization is canonical.
- Check intermediaries (proxies, WAFs, virus scanners) that could rewrite the body.
- Log and reject the offending request at the edge if you're seeing deliberate tampering.
Example fix
// before: hand-rolling the payload
const body = new Blob([JSON.stringify({ offsets: [-1, 'x'] })]);
// after: use the library's serializer output unchanged
await fetch(actionUrl, { method: 'POST', body: kitSerializedFormData }); Defensive patterns
Strategy: validation
Validate before calling
const offsets = parsed?.fileOffsets; const valid = Array.isArray(offsets) && offsets.every((n) => typeof n === 'number' && Number.isInteger(n) && n >= 0);
Type guard
function isValidOffsetTable(v) {
return Array.isArray(v) && v.every((n) => typeof n === 'number' && Number.isInteger(n) && n >= 0);
} Try / catch
try {
await deserialize_binary_form(request);
} catch (e) {
if (String(e.message).includes('invalid file offset table')) {
return new Response('Malformed request', { status: 400 });
}
throw e;
} Prevention
- Pin the same @sveltejs/kit version on client and server.
- Submit via use:enhance/native POST so payloads are canonical.
- Reject malformed bodies at the proxy/WAF before they reach the app.
When it happens
Trigger: A multipart/form-data action request whose binary payload contains an offset table that is not an array (e.g. an object or string) or contains negative/non-integer/non-number entries — typically from a hand-crafted request, corrupted transfer, or wrong serializer version on the client.
Common situations: Proxy or antivirus rewriting the body; client and server on mismatched SvelteKit versions with different binary framing; security scanners fuzzing action endpoints; manual replay of captured requests with edited content.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Could not deserialize binary form: duplicate file offset…
- Could not deserialize binary form: invalid file metadata
- Could not deserialize binary form: file offset table too…
- Could not deserialize binary form: gaps in file data
- Could not deserialize binary form: overlapping file data
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/41deb1a813fe7148.
Report an issue: GitHub.
Appendix: source
Thrown at packages/kit/src/runtime/form-utils.js:278
const data_buffer = await get_buffer(HEADER_BYTES, data_length);
if (!data_buffer) throw deserialize_error('data too short');
/** @type {Array<number | undefined>} */
let file_offsets;
/** @type {number} */
let files_start_offset;
if (file_offsets_length > 0) {
// Read the file offset table
const file_offsets_buffer = await get_buffer(HEADER_BYTES + data_length, file_offsets_length);
if (!file_offsets_buffer) throw deserialize_error('file offset table too short');
const parsed_offsets = JSON.parse(text_decoder.decode(file_offsets_buffer));
if (
!Array.isArray(parsed_offsets) ||
parsed_offsets.some((n) => typeof n !== 'number' || !Number.isInteger(n) || n < 0)
) {
throw deserialize_error('invalid file offset table');
}
file_offsets = /** @type {Array<number>} */ (parsed_offsets);
files_start_offset = HEADER_BYTES + data_length + file_offsets_length;
}
/** @type {Array<{ offset: number, size: number }>} */
const file_spans = [];
const [data, meta] = devalue.parse(text_decoder.decode(data_buffer), {
File: ([name, type, size, last_modified, index]) => {
if (
typeof name !== 'string' ||
typeof type !== 'string' ||
typeof size !== 'number' ||
typeof last_modified !== 'number' ||
typeof index !== 'number'
) {
throw deserialize_error('invalid file metadata');View on GitHub (pinned to 03f1687fe6)