can1357/oh-my-pi · error · ArchiveError

Invalid RPM package: null tag ${tag} has values

Error message

Invalid RPM package: null tag ${tag} has values

What it means

ArchiveError thrown by validateHeaderBody() when an index entry has type 0 (RPM NULL type) but a non-zero count. Per the RPM format, NULL entries carry no data, so count must be 0; this enforces that invariant while walking the header index.

Source

Thrown at packages/utils/src/ar/rpm.ts:89

function validateHeaderBody(body: Uint8Array, intro: HeaderIntro, what: string): void {
	const indexSize = intro.indexCount * RPM_INDEX_ENTRY_SIZE;
	if (body.byteLength !== intro.bodySize) throw new ArchiveError(`Invalid RPM package: truncated ${what} header`);
	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);
		const count = readUInt32BE(body, recordOffset + 12);
		if (offset > intro.dataSize) throw new ArchiveError(`Invalid RPM package: tag ${tag} points outside header data`);
		const remaining = intro.dataSize - offset;
		let elementSize = 0;
		if (type === 1 || type === 2 || type === 7) elementSize = 1;
		else if (type === 3) elementSize = 2;
		else if (type === 4) elementSize = 4;
		else if (type === 5) elementSize = 8;
		else if (type === 0) {
			if (count !== 0) throw new ArchiveError(`Invalid RPM package: null tag ${tag} has values`);
			continue;
		} else if (type === RPM_TYPE_STRING || type === 8 || type === 9) {
			const stringCount = type === RPM_TYPE_STRING ? 1 : count;
			if (type === RPM_TYPE_STRING && count !== 1) {
				throw new ArchiveError(`Invalid RPM package: string tag ${tag} has an invalid count`);
			}
			if (stringCount > remaining) {
				throw new ArchiveError(`Invalid RPM package: string tag ${tag} exceeds header data`);
			}
			let cursor = indexSize + offset;
			const limit = indexSize + intro.dataSize;
			for (let stringIndex = 0; stringIndex < stringCount; stringIndex++) {
				while (cursor < limit && body[cursor] !== 0) cursor++;
				if (cursor === limit) {
					throw new ArchiveError(`Invalid RPM package: string tag ${tag} is not NUL-terminated`);
				}
				cursor++;
			}

View on GitHub (pinned to 9690622007)

Solutions

  1. Rebuild/re-download the package with standard rpmbuild
  2. Verify checksums before parsing
  3. If generating headers yourself, set count=0 for NULL-type entries

Example fix

// before
{ tag: 1234, type: 0, offset: 0, count: 4 } // NULL with values
// after
{ tag: 1234, type: 0, offset: 0, count: 0 } // NULL entries carry no data
Defensive patterns

Strategy: try-catch

Validate before calling

// validate with standard tooling before parsing
const chk = await $`rpm -K ${path}`.quiet().nothrow();
if (chk.exitCode !== 0) throw new Error('rpm failed verification');

Type guard

null

Try / catch

try {
  const rpm = await readRpmArchive(buf);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('null tag')) {
    // reject non-conformant header
  } else throw err;
}

Prevention

When it happens

Trigger: Header index entry with type==0 and count!==0 — non-conformant header written by broken tooling, or corrupted index bytes.

Common situations: Packages produced by non-rpm tools or custom repackers, bit corruption in the index region, fuzzed inputs.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ccf47a089c6e2191. Report an issue: GitHub.