can1357/oh-my-pi · error · ArchiveError

Invalid RPM package: tag ${tag} must contain one string

Error message

Invalid RPM package: tag ${tag} must contain one string

What it means

readHeaderString extracts a single-string value for known metadata tags (NAME, VERSION, PAYLOAD_FORMAT, PAYLOAD_COMPRESSOR, PAYLOAD_FLAGS). Those tags must be typed STRING (6) with count 1; if the main header declares them otherwise (e.g. an INT32 version, or a string array), the parser refuses to decode them as strings rather than producing garbage.

Source

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

			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`);
	}
}

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");

View on GitHub (pinned to 9690622007)

Solutions

  1. Rebuild the package with standard rpmbuild so metadata tags are STRING type with count 1.
  2. If the file is downloaded, re-download and verify checksum — the type field may be corrupted.
  3. Inspect the header with `rpm -qp --qf` or `rpm2cpio | less` to see actual tag types.
  4. Catch ArchiveError around readRpm and fall back to lead-level identity (lead name) instead of header metadata.

Example fix

// before: trusting metadata presence
const entries = await readRpm(source, options);
// after: degrade gracefully when header metadata is malformed
let entries;
try {
  entries = await readRpm(source, options);
} catch (err) {
  if (err instanceof ArchiveError && /must contain one string/.test(err.message)) {
    entries = await readArchiveWithoutRpmMetadata(source, options);
  } else throw err;
}
Defensive patterns

Strategy: try-catch

Try / catch

let metadata;
try {
  metadata = (await readRpm(source, options)).metadata;
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes("must contain one string")) {
    metadata = { name: leadNameFallback }; // degrade to lead-level identity
  } else throw err;
}

Prevention

When it happens

Trigger: parseMainHeader (via readRpmArchive/readRpm) finds one of tags 1000/1001/1124/1125/1126 with type != 6 or count != 1, e.g. a package whose payload compressor tag is stored as a binary blob or array.

Common situations: Packages built by non-rpm tooling that stores metadata tags with wrong types; corruption flipping a tag's type field; experimental/custom header layouts.

Related errors


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