can1357/oh-my-pi · error · ArchiveError
Invalid RPM package: tag ${tag} string is not NUL-terminated
Error message
Invalid RPM package: tag ${tag} string is not NUL-terminated What it means
When decoding a single-string metadata tag, the parser scans for the NUL terminator within the header data region; reaching the region end without one means the string is unterminated. Even though validateHeaderBody already checks termination, this second check guards the value-extraction path (e.g. signature vs main header divergence) before decoding.
Source
Thrown at packages/utils/src/ar/rpm.ts:134
}
function readHeaderString(
body: Uint8Array,
indexSize: number,
dataSize: number,
offset: number,
count: number,
type: number,
tag: number,
): string {
if (type !== RPM_TYPE_STRING || count !== 1) {
throw new ArchiveError(`Invalid RPM package: tag ${tag} must contain one string`);
}
const start = indexSize + offset;
const limit = indexSize + dataSize;
let end = start;
while (end < limit && body[end] !== 0) end++;
if (end === limit) throw new ArchiveError(`Invalid RPM package: tag ${tag} string is not NUL-terminated`);
if (end - start > 4096) throw new ArchiveError(`Invalid RPM package: tag ${tag} string is too large`);
try {
return UTF8_FATAL_DECODER.decode(body.subarray(start, end));
} catch {
throw new ArchiveError(`Invalid RPM package: tag ${tag} is not valid UTF-8`);
}
}
function parseMainHeader(body: Uint8Array, intro: HeaderIntro): RpmMetadata {
validateHeaderBody(body, intro, "main");
const indexSize = intro.indexCount * RPM_INDEX_ENTRY_SIZE;
if (body.byteLength !== intro.bodySize) throw new ArchiveError("Invalid RPM package: truncated main header");
const metadata: RpmMetadata = {};
for (let index = 0; index < intro.indexCount; index++) {
const recordOffset = index * RPM_INDEX_ENTRY_SIZE;
const tag = readUInt32BE(body, recordOffset);
const type = readUInt32BE(body, recordOffset + 4);
const offset = readUInt32BE(body, recordOffset + 8);View on GitHub (pinned to 9690622007)
Solutions
- Re-download or rebuild the .rpm; the header data region is damaged.
- Verify truncation by comparing file size with the published checksum.
- Cross-check the header with `rpm -qp` to confirm corruption.
- Catch ArchiveError and reject/skip the package in your processing loop.
Defensive patterns
Strategy: try-catch
Validate before calling
if (fileSize < manifestSize) throw new Error("download incomplete"); Try / catch
try {
const entries = await readRpm(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("not NUL-terminated")) {
return reDownloadAndRetry(file); // truncation is the usual cause
}
throw err;
} Prevention
- Enforce complete downloads (Content-Length/checksum) before parsing.
- Retry with a fresh download when truncation is suspected.
- Parse at ingest time so corrupt files are caught early.
When it happens
Trigger: parseMainHeader calls readHeaderString for tag 1000/1001/1124/1125/1126 and the bytes from the tag offset to the end of the header data contain no 0 byte — typically because the header is truncated or its data size field is wrong.
Common situations: Incomplete downloads cutting off the header tail; corruption of the final NUL byte; headers rebuilt by tooling that miscounts dataSize.
Related errors
- Invalid RPM package: string tag ${tag} is not NUL-terminated
- Invalid RPM package: corrupt ${what} header magic
- Invalid RPM package: corrupt ${what} header reserved bytes
- Invalid RPM package: tag ${tag} points outside header data
- Invalid RPM package: null tag ${tag} has values
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e601f579323f992c.
Report an issue: GitHub.