can1357/oh-my-pi · error · ArchiveError

Unsupported RPM signature type ${signatureType}; only header

Error message

Unsupported RPM signature type ${signatureType}; only header signatures are supported

What it means

The lead's signature type field (big-endian u16 at offsets 78-79) is not 5 (RPMSIG_HEADERSIG). Only header-style signatures carry the parseable header structure this reader needs; legacy signature types (1-4) are rejected with the offending value in the message.

Source

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

			return lzmaAloneDecompress(payload, maxOutput);
		case "none":
			if (!sniffCpio(payload))
				throw new ArchiveError(`RPM package '${identity}' has an invalid uncompressed CPIO payload`);
			return payload;
		default:
			throw new ArchiveError(`RPM package '${identity}' uses unsupported payload compressor '${method}'`);
	}
}

async function readRpmArchive(source: ByteSource, options: FormatReadOptions): Promise<ArchiveIndexEntry[]> {
	const initial = await readExact(source, 0, RPM_LEAD_SIZE + RPM_HEADER_INTRO_SIZE, "lead and signature header");
	if (!sniffRpm(initial)) throw new ArchiveError("Invalid RPM package: bad lead magic");
	const major = initial[4]!;
	const packageType = (initial[6]! << 8) | initial[7]!;
	if (major < 3 || packageType > 1) throw new ArchiveError("Unsupported RPM package lead version or type");
	const signatureType = (initial[78]! << 8) | initial[79]!;
	if (signatureType !== RPM_SIGNATURE_TYPE_HEADER) {
		throw new ArchiveError(`Unsupported RPM signature type ${signatureType}; only header signatures are supported`);
	}
	const leadNameEnd = initial.subarray(10, 76).indexOf(0);
	const leadNameBytes = initial.subarray(10, leadNameEnd < 0 ? 76 : 10 + leadNameEnd);
	let leadName = "unknown package";
	try {
		const decoded = new TextDecoder("utf-8", { fatal: true }).decode(leadNameBytes);
		if (decoded) leadName = decoded;
	} catch {}

	const signatureIntro = parseHeaderIntro(initial.subarray(RPM_LEAD_SIZE), options, "signature");
	const signatureEnd = RPM_LEAD_SIZE + signatureIntro.totalSize;
	const mainHeaderOffset = align(signatureEnd, 8);
	const signatureBodyAndPadding = await readExact(
		source,
		RPM_LEAD_SIZE + RPM_HEADER_INTRO_SIZE,
		mainHeaderOffset,
		"signature header",
	);

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-download the package from a current repository — virtually all modern RPMs use signature type 5.
  2. Re-sign or repack the package with a modern rpm version (rpm --resign / rpmbuild) to convert to a header signature.
  3. If the file is genuinely ancient, extract it on a legacy rpm installation or via rpm2cpio in a container with an old rpm.
  4. Verify the artifact is not hand-modified; a wrong signatureType value suggests corruption or custom rewriting.
Defensive patterns

Strategy: validation

Validate before calling

async function rpmSignatureType(path: string): Promise<number | null> {
  const b = new Uint8Array(await Bun.file(path).slice(78, 80).arrayBuffer());
  if (b.length < 2) return null;
  return (b[0]! << 8) | b[1]!;
}
// require === 5 before reading

Type guard

function hasHeaderSignatureType(lead: Uint8Array): boolean {
  return ((lead[78] ?? 0) << 8 | (lead[79] ?? 0)) === 5;
}

Try / catch

try {
  return await readRpm(path);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('signature type')) {
    throw new Error('RPM uses a legacy signature type; re-sign/repack with modern rpm');
  }
  throw err;
}

Prevention

When it happens

Trigger: Reading an RPM whose lead declares a pre-header signature format (signatureType != 5), e.g. packages signed/stored with the old PGP/GPG non-header signature styles from very old rpm releases.

Common situations: Encountering museum-grade RPMs from pre-RPM 3 distributions, or files repacked by nonstandard tooling that wrote an obsolete signature type.

Related errors


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