{"record":{"id":"9d01663a03702a62","repo":"can1357/oh-my-pi","slug":"tar-numeric-value-does-not-fit-its-header-field","errorCode":null,"errorMessage":"Tar numeric value does not fit its header field","messagePattern":"Tar numeric value does not fit its header field","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/tar.ts","lineNumber":613,"sourceCode":"\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);\n\t\tconst name = pathBytes.subarray(index + 1);\n\t\tif (prefix.byteLength <= PREFIX_LENGTH && name.byteLength > 0 && name.byteLength <= NAME_LENGTH) {\n\t\t\treturn [name, prefix];\n\t\t}\n\t}\n\treturn undefined;\n}","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/tar.ts#L595-L631","documentation":"While encoding a tar header, a numeric field (size, mtime, mode, uid/gid) is written as zero-padded ASCII octal into a fixed-width header field. The library throws this when the value's octal representation has more digits than the field can hold (length-1 digits plus terminator). This prevents silently writing a truncated/corrupt tar header.","triggerScenarios":"Calling createTar (or appendTarEntry) with a file whose size exceeds the ustar size field limit (8 GB, since octal 77777777777 = 8589934591 bytes), an mtime beyond ~Oct 2242, or a uid/gid/mode too large for its field width.","commonSituations":"Archiving files larger than 8 GB with the ustar (not GNU/PAX) format; passing a Date.now()-in-milliseconds mtime instead of seconds; a corrupted or bogus size from a custom metadata source.","solutions":["Reduce member sizes below 8 GB or split large files before archiving","Pass mtime in seconds, not milliseconds (Math.floor(ms / 1000))","Verify size/mode/uid/gid values are the ustar-encoded numeric range expected","Switch to an archive format without the ustar size limit (zip, or a tar writer with PAX/GNU extensions)"],"exampleFix":"// before\nappendTarEntry(parts, path, hugeFileBytes, false, 0, { mtime: Date.now() });\n// after\nappendTarEntry(parts, path, hugeFileBytes, false, 0, { mtime: Math.floor(Date.now() / 1000) });","handlingStrategy":"validation","validationCode":"const USTAR_SIZE_LIMIT = 0o77777777777; // 8 GB - 1\nif (bytes.byteLength > USTAR_SIZE_LIMIT) {\n\tthrow new Error(`Member '${path}' exceeds ustar size field (${bytes.byteLength} bytes)`);\n}\nconst mtimeSec = Math.floor(mtimeMs / 1000);\nif (!Number.isSafeInteger(mtimeSec) || mtimeSec < 0 || mtimeSec > 0o7777777777) {\n\tthrow new Error(`mtime ${mtimeMs} out of ustar range`);\n}","typeGuard":null,"tryCatchPattern":"try {\n\tconst tar = await createTar(members);\n} catch (err) {\n\tif (err instanceof ArchiveError && err.message.includes(\"does not fit its header field\")) {\n\t\t// split oversized members or use a different format\n\t}\n\tthrow err;\n}","preventionTips":["Always pass mtime in seconds, never Date.now() directly","Check member sizes against the 8 GB ustar limit before encoding","Prefer zip or PAX tar for archives that may exceed ustar limits"],"tags":["archive","tar","validation"],"backgroundTag":"tar-header-numeric-overflow","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}