can1357/oh-my-pi · error · ArchiveError

Unsupported compress (.Z) header flags

Error message

Unsupported compress (.Z) header flags

What it means

The third byte of a .Z stream is a flags byte; bits 0x20 and 0x40 are reserved by the compress format and must be 0. This decoder rejects streams with those reserved bits set because their meaning is undefined and no known ncompress version emits them — such a stream is either corrupt or produced by a nonstandard compressor.

Source

Thrown at packages/utils/src/ar/codecs/lzw.ts:109

		grown.set(this.#bytes.subarray(0, this.#length));
		this.#bytes = grown;
	}
}

function decode(bytes: Uint8Array, maxOutput: number): Uint8Array {
	if (!Number.isSafeInteger(maxOutput) || maxOutput < 0) {
		throw new ArchiveError("Invalid compress (.Z) output limit");
	}
	if (bytes.byteLength < 3) {
		throw new ArchiveError("Truncated compress (.Z) header");
	}
	if (bytes[0] !== 0x1f || bytes[1] !== 0x9d) {
		throw new ArchiveError("Invalid compress (.Z) header");
	}

	const flags = bytes[2]!;
	if ((flags & 0x60) !== 0) {
		throw new ArchiveError("Unsupported compress (.Z) header flags");
	}
	const maxBits = flags & 0x1f;
	if (maxBits < MIN_BITS || maxBits > MAX_BITS) {
		throw new ArchiveError(`Invalid compress (.Z) maximum code width ${maxBits}`);
	}
	const blockMode = (flags & 0x80) !== 0;
	const dictionaryLimit = 2 ** maxBits;
	const parents = new Uint16Array(dictionaryLimit);
	const suffixes = new Uint8Array(dictionaryLimit);
	const stack = new Uint8Array(dictionaryLimit);
	const reader = new LsbCodeReader(bytes.subarray(3));
	const output = new BoundedOutput(maxOutput, bytes.byteLength);

	let width = MIN_BITS;
	let dictionaryHead = blockMode ? FIRST_BLOCK_CODE : 256;
	let needsPreviousSuffix = false;

	for (;;) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Treat the input as corrupt: re-obtain the .Z file from its original source and compare checksums.
  2. Check the provenance of the file — confirm it was produced by standard ncompress (flags byte should be 0x80-0x9f range, e.g. 0x90 for 16-bit block mode).
  3. If a custom compressor produced the stream, recompress it with standard ncompress before decoding.
  4. Report upstream if a trusted tool reliably emits such streams; this decoder intentionally does not guess at reserved-flag semantics.

Example fix

// before
await lzwDecompress(suspectBytes, limit); // throws on flags & 0x60
// after
const flags = suspectBytes[2] ?? 0;
if ((flags & 0x60) !== 0) {
  console.warn("nonstandard .Z flags, re-fetching/recompressing file");
}
await lzwDecompress(suspectBytes, limit);
Defensive patterns

Strategy: try-catch

Validate before calling

const flags = bytes[2] ?? 0;
if ((flags & 0x60) !== 0) throw new Error("Nonstandard .Z header flags 0x" + flags.toString(16) + " — re-acquire file");

Type guard

function hasSupportedZFlags(bytes: Uint8Array): boolean {
  return bytes.byteLength >= 3 && (bytes[2]! & 0x60) === 0;
}

Try / catch

try {
  return await lzwDecompress(bytes, maxOutput);
} catch (e) {
  if (e instanceof ArchiveError && e.message.includes("Unsupported compress (.Z) header flags")) {
    throw new Error(".Z stream uses reserved header flags; source file is corrupt or nonstandard");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling lzwDecompress on a stream whose header byte bytes[2] has bit 0x20 or 0x40 set (flags & 0x60 !== 0), e.g. a corrupted third byte or output of a nonstandard/patched compress implementation.

Common situations: A .Z file damaged by an editor/transfer layer that flipped header bits; archives produced by exotic or buggy compress clones; misinterpreted files from non-Unix sources that coincidentally carry the 1f 9d magic.

Related errors


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