{"record":{"id":"bccd21d2221dfe18","repo":"sveltejs/kit","slug":"could-not-deserialize-binary-form-duplicate-file","errorCode":null,"errorMessage":"Could not deserialize binary form: duplicate file offset table index","messagePattern":"Could not deserialize binary form: duplicate file offset table index","errorType":"exception","errorClass":"SvelteKitError","httpStatus":400,"severity":"error","filePath":"packages/kit/src/runtime/form-utils.js","lineNumber":304,"sourceCode":"\tconst file_spans = [];\n\tconst [data, meta] = devalue.parse(text_decoder.decode(data_buffer), {\n\t\tFile: ([name, type, size, last_modified, index]) => {\n\t\t\tif (\n\t\t\t\ttypeof name !== 'string' ||\n\t\t\t\ttypeof type !== 'string' ||\n\t\t\t\ttypeof size !== 'number' ||\n\t\t\t\ttypeof last_modified !== 'number' ||\n\t\t\t\ttypeof index !== 'number'\n\t\t\t) {\n\t\t\t\tthrow deserialize_error('invalid file metadata');\n\t\t\t}\n\n\t\t\tlet offset = file_offsets[index];\n\n\t\t\t// Check that the file offset table entry has not been already\n\t\t\t// used. If not, immediately mark it as used.\n\t\t\tif (offset === undefined) {\n\t\t\t\tthrow deserialize_error('duplicate file offset table index');\n\t\t\t}\n\t\t\tfile_offsets[index] = undefined;\n\n\t\t\toffset += files_start_offset;\n\n\t\t\tfile_spans.push({ offset, size });\n\n\t\t\treturn new Proxy(new LazyFile(name, type, size, last_modified, get_chunk, offset), {\n\t\t\t\tgetPrototypeOf() {\n\t\t\t\t\t// Trick validators into thinking this is a normal File\n\t\t\t\t\treturn File.prototype;\n\t\t\t\t}\n\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).","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/runtime/form-utils.js#L286-L322","documentation":"Each entry in the binary form's file offset table must be used by exactly one file's metadata 'index'. deserialize_binary_form marks each offset as used (sets it to undefined); if a second file references the same index, or an index is out of range, it throws this error to block duplicated or aliased file references.","triggerScenarios":"A multipart/form-data action request where two file entries share the same offset-table index, or where an index is >= the table length — from corrupted payloads, hand-crafted requests, or serializer/format mismatches.","commonSituations":"Fuzzing or deliberate tampering with action endpoints; middleware that rewrites the JSON section; version-skewed client/server binaries producing inconsistent index tables.","solutions":["Submit forms through SvelteKit's standard flow so indexes are generated correctly.","Match client/server @sveltejs/kit versions.","Reject malformed requests at proxy/WAF level if you're under attack.","Clear caches/redeploy if a stale mismatched client bundle is in circulation."],"exampleFix":"// before: reusing an index in custom serialization\nmeta.files = [{ name: 'a', index: 0 }, { name: 'b', index: 0 }];\n// after: unique index per file\nmeta.files = [{ name: 'a', index: 0 }, { name: 'b', index: 1 }];","handlingStrategy":"validation","validationCode":"const seen = new Set();\nfor (const f of meta.files) {\n  if (seen.has(f.index)) throw new Error('duplicate file index ' + f.index);\n  seen.add(f.index);\n}","typeGuard":"function hasUniqueIndexes(files) {\n  const seen = new Set();\n  return files.every((f) => !seen.has(f.index) && seen.add(f.index) !== undefined);\n}","tryCatchPattern":"try {\n  await deserialize_binary_form(request);\n} catch (e) {\n  if (String(e.message).includes('duplicate file offset table index')) {\n    return new Response('Malformed request', { status: 400 });\n  }\n  throw e;\n}","preventionTips":["Assign unique indexes when serializing files.","Never hand-edit serialized payloads.","Align kit versions to avoid format drift."],"tags":["sveltekit","forms","serialization","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}