can1357/oh-my-pi · error · ArchiveError

Invalid RPM package: string tag ${tag} exceeds header data

Error message

Invalid RPM package: string tag ${tag} exceeds header data

What it means

For string-family tags (STRING=6, string array=8, I18N string=9), the parser checks that the declared number of strings can physically fit between the tag's data offset and the end of the header data region. If stringCount > remaining bytes, the index entry points at more data than the header actually contains, so the header is inconsistent and parsing stops.

Source

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

		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++;
			}
			continue;
		} else {
			throw new ArchiveError(`Invalid RPM package: tag ${tag} uses unknown data type ${type}`);
		}
		if (offset % elementSize !== 0) throw new ArchiveError(`Invalid RPM package: tag ${tag} data is misaligned`);
		if (count * elementSize > remaining)
			throw new ArchiveError(`Invalid RPM package: tag ${tag} exceeds header data`);
	}

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-acquire the .rpm file; the header is internally inconsistent, so it cannot be parsed.
  2. Cross-check with `rpm -qp` to confirm corruption.
  3. Ensure the upstream source serving the file is not truncating it (proxy, partial upload).
  4. Wrap readRpm in try-catch on ArchiveError and surface a clear 'corrupt package' message to users.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: file should at least contain lead (96) + header bytes; verify expected size from your source manifest before parsing
if (fileSize < manifestExpectedSize) throw new Error("package truncated before parse");

Try / catch

try {
  const entries = await readRpm(source, options);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes("exceeds header data")) {
    logger.warn("RPM header inconsistent", { file });
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: readRpm()/parseMainHeader validates a header whose index entry declares a string (or string-array) tag with an offset near the end of the data region and a count that overruns dataSize (e.g. offset = dataSize - 1 with a 3-element string array).

Common situations: Truncated or corrupted .rpm downloads; bit-flipped count/offset fields in the header; maliciously crafted packages designed to cause out-of-bounds reads (this check prevents that); archives misrouted into the RPM reader.

Related errors


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