{"record":{"id":"f18b99ee471b35cc","repo":"can1357/oh-my-pi","slug":"invalid-lzh-symbolic-link-header-path","errorCode":null,"errorMessage":"Invalid LZH symbolic link '${header.path}'","messagePattern":"Invalid LZH symbolic link '(.+?)'","errorType":"validation","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/lzh.ts","lineNumber":629,"sourceCode":"\t}\n\tif (bytes.byteLength !== source.size) throw new ArchiveError(\"Invalid LZH archive: truncated data\");\n\tif (!sniffLzh(bytes)) throw new ArchiveError(\"Invalid LZH archive header\");\n\tconst entries: ArchiveIndexEntry[] = [];\n\tlet offset = 0;\n\tlet parsedCount = 0;\n\tlet metadataSize = 0;\n\twhile (offset < bytes.byteLength && bytes[offset] !== 0) {\n\t\tconst header = parseLzhHeader(bytes, offset, options);\n\t\tmetadataSize += header.dataStart - offset;\n\t\tassertIndexSize(metadataSize, options.limits, \"index\");\n\t\tassertEntryCount(++parsedCount, options.limits);\n\t\tif (header.nextOffset <= offset) throw new ArchiveError(\"Invalid LZH archive: header did not advance\");\n\t\toffset = header.nextOffset;\n\t\tif (!header.path) continue;\n\t\tconst isDirectory = header.method === \"-lhd-\";\n\t\tif (isDirectory && header.mode !== undefined && (header.mode & 0xf000) === 0xa000) {\n\t\t\tconst separator = header.path.indexOf(\"|\");\n\t\t\tif (separator < 1) throw new ArchiveError(`Invalid LZH symbolic link '${header.path}'`);\n\t\t\tconst path = normalizeArchiveEntryPath(header.path.slice(0, separator));\n\t\t\tconst targetPath = normalizeArchiveEntryPath(header.path.slice(separator + 1));\n\t\t\tif (!path || !targetPath) continue;\n\t\t\tentries.push({\n\t\t\t\tpath,\n\t\t\t\tisDirectory: false,\n\t\t\t\tsize: 0,\n\t\t\t\tmtimeMs: header.mtimeMs,\n\t\t\t\tmode: header.mode,\n\t\t\t\tstorage: { type: \"link\", targetPath, resolveTarget: false },\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tentries.push({\n\t\t\tpath: header.path,\n\t\t\tisDirectory,\n\t\t\tsize: isDirectory ? 0 : header.size,\n\t\t\tmtimeMs: header.mtimeMs,","sourceCodeStart":611,"sourceCodeEnd":647,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/lzh.ts#L611-L647","documentation":"A directory entry (-lhd-) whose mode indicates a symlink (S_IFLNK, 0xa000) must encode its link target after a '|' separator in the path ('linkpath|target'). If the path has no '|' or the '|' would start the link name (index < 1), the entry is malformed and cannot be interpreted as a symbolic link.","triggerScenarios":"readLzh() on an LZH archive containing a -lhd- entry with symlink mode bits but a path missing the 'link|target' separator, e.g. 'foo|' or just 'foo'.","commonSituations":"Archives produced by tools that store symlinks non-standardly; corrupted path fields; hand-built archives where the symlink encoding convention was not followed.","solutions":["Inspect the offending member with an external LHA tool to see its raw path and mode.","Recreate the archive with a tool that encodes symlinks as 'linkpath|target' (e.g. modern lha/lhasa on Unix).","If the entry should be a plain directory, correct its mode (remove the S_IFLNK bits) rather than -lhd- with 0xa000.","Catch ArchiveError and skip/flag the archive if symlink metadata is not needed."],"exampleFix":"// before: creating a symlink member with the wrong path encoding\npath = \"mylink\"; // missing target\n// after: encode as link|target\npath = \"mylink|/etc/hostname\";","handlingStrategy":"validation","validationCode":"// pre-screen symlink-style directory entries before reading\n// (readLzh throws for -lhd- + S_IFLNK without 'link|target' encoding)\n// prefer archives created by tools known to encode symlinks correctly\nif (!createdByModernLhaTool(archive)) {\n  await validateSymlinkEntriesExternally(path); // e.g. `lha l` output check\n}","typeGuard":null,"tryCatchPattern":"try {\n  const entries = await readLzh(source, options);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.startsWith(\"Invalid LZH symbolic link\")) {\n    throw new Error(\"archive stores symlinks in a non-standard way — repack with lha/lhasa\");\n  }\n  throw err;\n}","preventionTips":["Create Unix archives with tools that encode symlinks as 'linkpath|target'","Avoid mixing DOS-era LZH tools with Unix symlink metadata","Repack legacy archives once with a modern tool and store the result"],"tags":["archive","lzh","symlink","malformed-metadata"],"backgroundTag":"malformed-archive-entry","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}