{"record":{"id":"4594ba805c2f5e28","repo":"can1357/oh-my-pi","slug":"archive-field-exceeds-maxpathbytes-bytes","errorCode":null,"errorMessage":"Archive ${field} exceeds ${maxPathBytes} bytes","messagePattern":"Archive (.+?) exceeds (.+?) bytes","errorType":"validation","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/paths.ts","lineNumber":63,"sourceCode":"/** Clamp an attacker-controlled path to a short preview for error messages. */\nexport function formatArchivePathForError(value: string): string {\n\tif (Buffer.byteLength(value, \"utf-8\") <= PATH_ERROR_PREVIEW_BYTES) return value;\n\n\tlet end = 0;\n\tlet size = 0;\n\tfor (const char of value) {\n\t\tconst charSize = Buffer.byteLength(char, \"utf-8\");\n\t\tif (size + charSize > PATH_ERROR_PREVIEW_BYTES - 3) break;\n\t\tend += char.length;\n\t\tsize += charSize;\n\t}\n\treturn `${value.slice(0, end)}...`;\n}\n\n/** Reject a member path/link target longer than `maxPathBytes`. */\nexport function assertArchivePathBytes(size: number, field: string, maxPathBytes: number): void {\n\tif (size > maxPathBytes) {\n\t\tthrow new ArchiveError(`Archive ${field} exceeds ${maxPathBytes} bytes`);\n\t}\n}\n\n/** {@link assertArchivePathBytes} for an already-decoded string. */\nexport function assertArchivePathString(value: string, field: string, maxPathBytes: number): void {\n\tassertArchivePathBytes(Buffer.byteLength(value, \"utf-8\"), field, maxPathBytes);\n}\n","sourceCodeStart":45,"sourceCodeEnd":71,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/paths.ts#L45-L71","documentation":"assertArchivePathBytes rejected a member path or link target whose UTF-8 byte length exceeds the configured per-entry path limit. Each format reader (ARJ, ASAR, CAB, CPIO, Rock Ridge merge, link-target builders) enforces this ceiling to prevent resource exhaustion and absurd path names. The message names the field and the byte limit.","triggerScenarios":"Reading any archive whose entry name or symlink target is longer than maxPathBytes — e.g. a tar member name over the limit passed via FormatReadOptions.limits, or a Rock Ridge NM field exceeding the ceiling during metadata merge.","commonSituations":"Archives containing machine-generated hash-named paths (node_modules, build caches) with extremely deep/long names; fuzzed or corrupt archives with gigantic name fields; callers lowering maxPathBytes below what a legitimate archive needs.","solutions":["Raise the path-bytes limit in the options you pass (limits.maxPathBytes or the relevant ArchiveLimits field) to accommodate the archive.","Repack the archive with shorter member paths (flatten directories, hash-shrink names).","Identify the offending entry via the archive index and remove it before processing.","Keep the default limits if the archive is untrusted — a huge path often signals a fuzzed or hostile input."],"exampleFix":"// before\nconst reader = await openArchive(input); // default path-bytes limit\n// after\nconst reader = await openArchive(input, { limits: { maxPathBytes: 4096 } });","handlingStrategy":"try-catch","validationCode":"const MAX = 4096;\nconst reader = await openArchive(src);\nfor (const e of reader.indexEntries()) {\n  if (Buffer.byteLength(e.path, \"utf8\") > MAX) throw new Error(`path too long: ${e.path.slice(0, 64)}...`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await extractArchive(src, dest);\n} catch (err) {\n  if (err instanceof ArchiveError && /exceeds \\d+ bytes/.test(err.message)) {\n    // retry with a higher limits.maxPathBytes or skip the entry\n  }\n  throw err;\n}","preventionTips":["Set limits.maxPathBytes deliberately based on the archives you expect (node_modules-style trees need generous limits).","Pre-scan the index for long names before extraction.","Repack archives with flattened/short member paths when feasible.","Keep strict limits for untrusted input; long paths often indicate fuzzed data."],"tags":["archive","path-length","limits","validation"],"backgroundTag":"archive-path-limit-exceeded","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}