ruvnet/ruflo · error
zstd decompression is not supported in this environment
Error message
zstd decompression is not supported in this environment
What it means
extractSection hit a section with compression === 'zstd'. Node core has no zstd support, so the reader attempts gunzipSync as a fallback (mirroring RvfaWriter, which silently downgrades zstd requests to gzip); if the bytes aren't gzip either, this error is thrown. Images written by RvfaWriter never contain real zstd sections — the downgrade guarantees compression==='gzip' — so a genuine zstd section means the image came from an external tool.
Solutions
- Rebuild or re-pack the image with compression 'gzip' or 'none' — RvfaWriter.addSection(id, data, { compression: 'gzip' }) — since the Node reader fully supports those
- Pre-check the section's compression field (reader.getSections()) and shell out to an external zstd binary for those sections instead of calling extractSection
- If you control the external writer, disable zstd or emit gzip for compatibility with this reader
- Track the upstream limitation: any real zstd support would require a native module (e.g. @mongodb-js/zstd or fzstd), absent from this implementation
Example fix
// before — extractSection throws on zstd sections
const data = reader.extractSection('kernel');
// after — branch on the declared compression
const sec = reader.getSections().find((s) => s.id === 'kernel')!;
if (sec.compression === 'zstd') {
const raw = fs.readFileSync(path).subarray(sec.offset, sec.offset + sec.size);
data = zstdDecompress(raw); // external zstd implementation
} else {
data = reader.extractSection('kernel');
} Defensive patterns
Strategy: fallback
Validate before calling
const sec = reader.getSections().find((s) => s.id === id);
if (sec?.compression === 'zstd') {
throw new Error('zstd section needs an external decompressor');
} Type guard
function isExtractableHere(sec: { compression: string }): boolean {
return sec.compression === 'none' || sec.compression === 'gzip';
} Try / catch
try { data = reader.extractSection(id); }
catch (e) {
if (/zstd decompression is not supported/.test(String((e as Error).message))) {
// fallback: decompress sec's raw range with an external zstd implementation
}
throw e;
} Prevention
- Build images with compression 'gzip' or 'none' when this Node reader will consume them
- Pre-check section.compression via getSections() before extracting
- Standardize the toolchain: any real-zstd writer will be unreadable here
When it happens
Trigger: extractSection(id) where header.sections[i].compression === 'zstd' AND the payload is actual zstd (not gzip). Happens with .rvfa images produced by third-party/Rust tooling that wrote real zstd frames, then consumed by this Node reader.
Common situations: Mixed toolchains: an appliance built with a Rust/Go packager (native zstd) read back by @claude-flow/cli; newer external tools defaulting to zstd for better ratio; CI promoting images between heterogeneous builders and readers.
Related errors
- Buffer too small to be a valid RVFA file
- Buffer too small to contain declared header
- Buffer too small to contain RVFA preamble
- Failed to parse RVFA header JSON
- Failed to parse RVFA header JSON
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/2ae5fa7344d7d90b.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/appliance/rvfa-format.ts:429
if (!sec) {
throw new Error(`Section "${id}" not found`);
}
if (sec.offset + sec.size > this.buf.length - SHA256_SIZE) {
throw new Error(`Section "${id}" exceeds buffer bounds`);
}
const raw = this.buf.subarray(sec.offset, sec.offset + sec.size);
if (sec.compression === 'gzip') {
return gunzipSync(raw);
}
if (sec.compression === 'zstd') {
// zstd not natively supported — attempt gzip fallback (mirrors writer)
try {
return gunzipSync(raw);
} catch {
throw new Error(
'zstd decompression is not supported in this environment',
);
}
}
// compression === 'none'
return Buffer.from(raw);
}
/**
* Verify the integrity of the RVFA image.
*
* Checks:
* 1. Magic bytes
* 2. Version number
* 3. SHA256 of each section's compressed data
* 4. SHA256 footer (all section data combined)
*/View on GitHub (pinned to fa13ee4ad6)