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

  1. Rebuild or re-pack the image with compression 'gzip' or 'none' — RvfaWriter.addSection(id, data, { compression: 'gzip' }) — since the Node reader fully supports those
  2. Pre-check the section's compression field (reader.getSections()) and shell out to an external zstd binary for those sections instead of calling extractSection
  3. If you control the external writer, disable zstd or emit gzip for compatibility with this reader
  4. 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

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


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)