{"record":{"id":"e4136275f1f89cb5","repo":"can1357/oh-my-pi","slug":"tar-header-field-is-too-long","errorCode":null,"errorMessage":"Tar header field is too long","messagePattern":"Tar header field is too long","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/tar.ts","lineNumber":606,"sourceCode":"\tif (bytes.byteLength !== source.size) throw new ArchiveError(\"Invalid archive: truncated data\");\n\treturn readTarEntriesFromBuffer(bytes, options);\n};\n\n/** Detect a tar header, including legacy pre-ustar archives, by its checksum. */\nexport function sniffTar(bytes: Uint8Array): boolean {\n\tif (bytes.byteLength < BLOCK_SIZE) return false;\n\tif (isZeroBlock(bytes, 0)) return true;\n\ttry {\n\t\tif (readTarString(bytes, NAME_OFFSET, NAME_LENGTH).length === 0) return false;\n\t\tconst size = readTarSize(bytes, SIZE_OFFSET);\n\t\treturn Number.isSafeInteger(paddedSize(size)) && checksumMatches(bytes, 0);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction writeField(target: Uint8Array, offset: number, length: number, value: Uint8Array): void {\n\tif (value.byteLength > length) throw new ArchiveError(\"Tar header field is too long\");\n\ttarget.set(value, offset);\n}\n\nfunction writeOctal(target: Uint8Array, offset: number, length: number, value: number): void {\n\tif (!Number.isSafeInteger(value) || value < 0) throw new ArchiveError(\"Invalid tar numeric value\");\n\tconst digits = value.toString(8);\n\tif (digits.length > length - 1) throw new ArchiveError(\"Tar numeric value does not fit its header field\");\n\tfor (let index = offset; index < offset + length - 1 - digits.length; index++) target[index] = 0x30;\n\tfor (let index = 0; index < digits.length; index++)\n\t\ttarget[offset + length - 1 - digits.length + index] = digits.charCodeAt(index);\n\ttarget[offset + length - 1] = 0;\n}\n\nfunction splitUstarPath(pathBytes: Uint8Array): readonly [Uint8Array, Uint8Array] | undefined {\n\tif (pathBytes.byteLength <= NAME_LENGTH) return [pathBytes, new Uint8Array(0)];\n\tfor (let index = pathBytes.byteLength - 1; index > 0; index--) {\n\t\tif (pathBytes[index] !== 0x2f) continue;\n\t\tconst prefix = pathBytes.subarray(0, index);","sourceCodeStart":588,"sourceCodeEnd":624,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/tar.ts#L588-L624","documentation":"When writing (serializing) a tar header, each field occupies a fixed number of bytes. writeField throws this ArchiveError if the value bytes exceed the field's fixed length. This guards against silently producing a corrupt archive with overlapping fields.","triggerScenarios":"Calling the tar writer with a name, link name, or other field whose UTF-8 encoding is longer than the fixed header slot (e.g. name > 100 bytes for plain ustar when no prefix split or pax record is applied).","commonSituations":"Very long file paths or deep directory trees written without ustar prefix splitting or GNU/pax long-name extension; long symlink targets; usernames/groupnames over 32 bytes.","solutions":["Let the writer emit PAX (pax_header) records for long paths instead of forcing plain ustar layout","Shorten the member path before writing (strip or rebase the leading directories)","If writing manually, split the path into prefix/name via splitUstarPath logic, or use GNU longname ('././@LongLink') extension","Check the encoded byte length (Buffer.byteLength, not string length) against the field limit before writing"],"exampleFix":"// before: long path blows the 100-byte name field\naddEntry({ path: `very/long/${repeat}/file.txt`, ... });\n// after: rebase so the stored path fits\naddEntry({ path: `very/long/${repeat}/file.txt`.replace(/^very\\/long\\//, \"\"), ... });","handlingStrategy":"validation","validationCode":"const encoded = Buffer.byteLength(entryPath, \"utf-8\");\nif (encoded > 100) {\n  // ensure the writer supports pax/GNU long names, or shorten the path first\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep member paths under 100 bytes or rely on the ustar prefix split (prefix <=155, name >0 and <=100)","Prefer writers that auto-emit PAX records for long names","Measure paths in bytes (UTF-8), not characters"],"tags":["tar","writer","header","field-length","path-length"],"backgroundTag":"tar-field-overflow","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}