{"record":{"id":"53fbc81f816b360c","repo":"sveltejs/kit","slug":"could-not-deserialize-binary-form-overlapping-fil","errorCode":null,"errorMessage":"Could not deserialize binary form: overlapping file data","messagePattern":"Could not deserialize binary form: overlapping file data","errorType":"exception","errorClass":"SvelteKitError","httpStatus":400,"severity":"error","filePath":"packages/kit/src/runtime/form-utils.js","lineNumber":335,"sourceCode":"\t\t\t});\n\t\t}\n\t});\n\n\t// Sort file spans in increasing order primarily by offset\n\t// and secondarily by size (to allow 0-length files).\n\tfile_spans.sort((a, b) => a.offset - b.offset || a.size - b.size);\n\n\t// Check that file spans do not overlap and there are no gaps between them.\n\tfor (let i = 1; i < file_spans.length; i++) {\n\t\tconst previous = file_spans[i - 1];\n\t\tconst current = file_spans[i];\n\n\t\tconst previous_end = previous.offset + previous.size;\n\t\tif (previous_end < current.offset) {\n\t\t\tthrow deserialize_error('gaps in file data');\n\t\t}\n\t\tif (previous_end > current.offset) {\n\t\t\tthrow deserialize_error('overlapping file data');\n\t\t}\n\t}\n\n\t// Read the request body asynchronously so it doesn't stall\n\tvoid (async () => {\n\t\tlet has_more = true;\n\t\twhile (has_more) {\n\t\t\tconst chunk = await get_chunk(chunks.length);\n\t\t\thas_more = !!chunk;\n\t\t}\n\t})().catch(noop); // prevent unhandled rejection potentially crashing the process\n\n\treturn { data, meta, form_data: null };\n}\n/**\n * @param {string} message\n */\nfunction deserialize_error(message) {","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/runtime/form-utils.js#L317-L353","documentation":"Companion check to 'gaps in file data': if one file's declared region extends past the next file's start offset, the regions overlap and the payload is inconsistent. deserialize_binary_form throws this to prevent corrupted or maliciously overlapping byte ranges from being extracted as files.","triggerScenarios":"A multipart/form-data action request whose offset table and file sizes define overlapping byte ranges — from tampered payloads, hand-crafted requests, or mismatched serializer versions.","commonSituations":"Attackers probing action endpoints with crafted offsets; middleware rewriting payload sections; version skew between client and server binary formats.","solutions":["Keep @sveltejs/kit versions identical on client and server.","Only submit via SvelteKit's canonical serialization path.","Reject malformed requests at the edge; log source IPs if it looks like probing.","Confirm no middleware mutates the JSON metadata of the request body."],"exampleFix":"// before: overlapping spans\noffsets: [0, 30], sizes: [50, 20] // file 1 ends at 50 > next start 30\n// after: non-overlapping spans\noffsets: [0, 50], sizes: [50, 20]","handlingStrategy":"validation","validationCode":"spans.sort((a, b) => a.offset - b.offset);\nfor (let i = 1; i < spans.length; i++) {\n  if (spans[i - 1].offset + spans[i - 1].size > spans[i].offset) throw new Error('overlapping spans');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await deserialize_binary_form(request);\n} catch (e) {\n  if (String(e.message).includes('overlapping file data')) {\n    return new Response('Malformed request', { status: 400 });\n  }\n  throw e;\n}","preventionTips":["Only accept payloads from kit's serializer; reject at edge if probed.","Keep client/server kit versions matched.","Don't let middleware mutate payload metadata."],"tags":["sveltekit","forms","serialization","integrity"],"backgroundTag":"binary-payload-corruption","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}