{"record":{"id":"c8b95641057667f0","repo":"can1357/oh-my-pi","slug":"not-a-valid-tar-archive-missing-terminating-zero","errorCode":null,"errorMessage":"Not a valid tar archive: missing terminating zero block","messagePattern":"Not a valid tar archive: missing terminating zero block","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/tar.ts","lineNumber":573,"sourceCode":"\t\t\t\tentry.storage = { type: \"link\", targetPath: portableLinkName, resolveTarget: false };\n\t\t\t\taddEntry(entry);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\taddEntry(entry, { kind, targetPath });\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeFlag !== \"0\" && typeFlag !== \"\\0\" && typeFlag !== \"7\" && typeFlag !== \"S\") continue;\n\t\tassertArchiveMemberSize(displaySize, normalizedPath, limits);\n\t\taddEntry({\n\t\t\tpath: normalizedPath,\n\t\t\tisDirectory: false,\n\t\t\tsize: displaySize,\n\t\t\tmtimeMs,\n\t\t\tmode,\n\t\t\tstorage: { type: \"member\", source: new TarMemberSource(buffer, dataOffset, sparse) },\n\t\t});\n\t}\n\tif (!sawTerminator) throw new ArchiveError(\"Not a valid tar archive: missing terminating zero block\");\n\tresolvePendingLinks(entries, pendingLinks, limits);\n\treturn [...entries.values()];\n}\n\n/** Read and index a tar source after one bounded whole-stream read. */\nexport const readTar: FormatReader = async (source, options) => {\n\tassertInMemorySize(source.size, options.limits);\n\tlet bytes: Uint8Array;\n\ttry {\n\t\tbytes = await readAllBytes(source);\n\t} catch (error) {\n\t\tif (error instanceof ArchiveError) throw error;\n\t\tthrow new ArchiveError(error instanceof Error ? error.message : \"Failed to read tar archive\");\n\t}\n\tif (bytes.byteLength !== source.size) throw new ArchiveError(\"Invalid archive: truncated data\");\n\treturn readTarEntriesFromBuffer(bytes, options);\n};\n","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/tar.ts#L555-L591","documentation":"This library validates that a tar archive ends with the two consecutive 512-byte zero blocks required by the tar format. If it reaches the end of the data without having seen that terminator, it refuses to index the archive and throws this ArchiveError. It is a structural integrity check: tar archives without the terminator are considered malformed or truncated, not merely odd.","triggerScenarios":"Calling readTar (or readTarEntriesFromBuffer) on a byte buffer that ends after the last file's data blocks without the terminating zero blocks — e.g. a tar written by a custom/naive writer, a stream cut off mid-archive, or a tar concatenated with padding stripped.","commonSituations":"Downloads interrupted before completion, pipes closed early (curl ... | tar-like flows captured partially), hand-rolled tar writers that forget the terminator, archives produced by tools emitting 'streaming' tar without end-of-archive markers, files truncated on disk after a crash.","solutions":["Re-obtain or re-extract the archive; the source is truncated — verify byte size against the upstream checksum","Rebuild the tar with a standard tool (`tar -cf`) so the terminating zero blocks are written","Pad the buffer manually with two 512-byte zero blocks if you control generation and know the data is otherwise complete","Check the producer: if you write tars yourself, append two zeroed 512-byte blocks after the last member"],"exampleFix":"// before: hand-rolled writer omits the terminator\nblocks.push(...memberBlocks);\nawait Bun.write(out, blocks);\n// after: append the required two zero blocks\nconst terminator = new Uint8Array(2 * 512);\nawait Bun.write(out, [blocks, terminator]);","handlingStrategy":"validation","validationCode":"function isTerminatedTar(bytes: Uint8Array): boolean {\n  if (bytes.byteLength % 512 !== 0) return false;\n  const end = bytes.byteLength - 1024;\n  if (end < 0) return false;\n  return bytes.subarray(end).every((b) => b === 0);\n}\nif (!isTerminatedTar(bytes)) throw new Error(\"tar archive lacks terminating zero blocks\");","typeGuard":null,"tryCatchPattern":"try {\n  const entries = await readTar(source, options);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"missing terminating zero block\")) {\n    // treat as corrupted/truncated download: re-fetch or surface to user\n  } else throw err;\n}","preventionTips":["Verify checksums (sha256) of downloaded archives before reading","Use standard tar tooling to produce archives — never hand-roll the terminator","When piping, wait for the writer process to exit before reading the file"],"tags":["tar","archive","truncated","format-validation"],"backgroundTag":"tar-archive-missing-terminator","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}