can1357/oh-my-pi · error · ArchiveError
Invalid compress (.Z) output limit
Error message
Invalid compress (.Z) output limit
What it means
decode() validates its maxOutput parameter before touching the stream: it must be a non-negative safe integer. This is an argument-validation error — the caller passed an invalid bound (negative, NaN, non-integer, or > Number.MAX_SAFE_INTEGER), not a data problem.
Source
Thrown at packages/utils/src/ar/codecs/lzw.ts:98
if (!Number.isSafeInteger(needed) || needed > this.#limit) {
throw new ArchiveError(`Compress (.Z) output exceeds the ${this.#limit}-byte limit`);
}
if (needed <= this.#bytes.byteLength) {
return;
}
let capacity = Math.max(needed, Math.min(this.#limit, Math.max(64, this.#bytes.byteLength * 2)));
if (capacity > this.#limit) {
capacity = this.#limit;
}
const grown = new Uint8Array(capacity);
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;View on GitHub (pinned to 9690622007)
Solutions
- Validate maxOutput at the call site: a non-negative safe integer before calling lzwDecompress.
- Fix the source of the value — check parseInt/Number conversions for NaN and config parsing for missing fields.
- Provide a sensible default (e.g. 256MB) when the configured limit is absent.
- Guard with Number.isSafeInteger(maxOutput) && maxOutput >= 0 before calling.
Example fix
// before: unparsed config
const max = Number(config.maxZOutput);
lzwDecompress(bytes, max);
// after
const max = Number(config.maxZOutput);
if (!Number.isSafeInteger(max) || max < 0) throw new Error("Invalid maxZOutput config");
lzwDecompress(bytes, max); Defensive patterns
Strategy: validation
Validate before calling
function assertValidMaxOutput(maxOutput: number): void {
if (!Number.isSafeInteger(maxOutput) || maxOutput < 0) {
throw new Error(`maxOutput must be a non-negative safe integer, got ${maxOutput}`);
}
} Type guard
function isValidMaxOutput(v: unknown): v is number {
return typeof v === "number" && Number.isSafeInteger(v) && v >= 0;
} Try / catch
try {
return lzwDecompress(bytes, maxOutput);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("output limit")) {
throw new Error(`Bad maxOutput argument: ${maxOutput}`, { cause: err });
}
throw err;
} Prevention
- Check Number.isSafeInteger(v) && v >= 0 on any configured limit before calling.
- Guard parseInt/Number conversions against NaN at the config boundary.
- Centralize limit parsing in one validated helper.
- Provide safe defaults when config values are missing.
When it happens
Trigger: Calling lzwDecompress(data, maxOutput) with maxOutput = -1, NaN, a float, undefined coerced oddly, or an unsafe integer computed from bad metadata.
Common situations: maxOutput read from a config file or env var without parsing validation; a NaN from a failed parseInt/Number conversion; arithmetic overflow producing Infinity before the call.
Related errors
- Truncated compress (.Z) header
- ${error instanceof Error ? error.message : String(error)}
- Truncated compress (.Z) code group
- Invalid non-zero compress (.Z) padding
- Compress (.Z) output exceeds the ${this.#limit}-byte limit
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/26824b09f51f3562.
Report an issue: GitHub.