facebook/flow · error

Parser out of memory

Error message

Parser out of memory

What it means

The oxidized flow-parser (WASM build) allocates a buffer for the source text with FlowParserWASM._malloc(sourceBuffer.length + 1); a return of 0 means the wasm heap is exhausted and it throws 'Parser out of memory'. Allocation lives inside try/finally so the failed allocation is still cleaned up; the error means the source (or the environment) is too large for the available wasm memory.

Solutions

  1. Skip or split the oversized file: chunk or trim generated files before parsing.
  2. Retry in a fresh process so wasm heap fragmentation from prior parses is cleared.
  3. Raise the memory available to Node (e.g. --max-old-space-size) or move to a 64-bit, higher-memory environment.
  4. Gate parsing on file size (e.g. skip >5MB) so pipelines degrade gracefully instead of throwing.

Example fix

// before
const ast = parse(fs.readFileSync(hugeBundle, 'utf8'));

// after
const code = fs.readFileSync(file, 'utf8');
if (Buffer.byteLength(code) > 5 * 1024 * 1024) throw new SkipError(file);
const ast = parse(code);
Defensive patterns

Strategy: try-catch

Validate before calling

// Gate parsing on input size
const MAX_PARSE_BYTES = 5 * 1024 * 1024;
function isParsableSize(code) {
  return Buffer.byteLength(code, 'utf8') <= MAX_PARSE_BYTES;
}

Try / catch

try {
  ast = parse(code, {flow: 'all'});
} catch (e) {
  if (e.message === 'Parser out of memory') {
    markSkipped(file, 'too large for wasm heap'); // do not retry the same input in-process
  } else throw e;
}

Prevention

When it happens

Trigger: parse() on very large files (multi-megabyte, e.g. machine-generated JS/bundles) that exceed the WASM heap; parsing many large files in one process without allowing prior allocations to be freed; constrained environments (low-memory containers, 32-bit limits) shrinking available wasm memory.

Common situations: Parsing generated artifacts (bundle output, JSON-to-JS data files, protobuf-generated code) in lint/translation pipelines; running parsers in memory-capped CI containers.

Related errors


AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20). Data as JSON: /api/errors/24734ba32f036c3e. Report an issue: GitHub.

Appendix: source

Thrown at packages/flow-parser/oxidized-src/FlowParser.js:228

  // non-ambient defaults.
  const filename =
    typeof options.sourceFilename === 'string' ? options.sourceFilename : '';
  const filenameBuffer =
    filename.length > 0 ? Buffer.from(filename, 'utf8') : null;

  // All wasm allocations live inside a single try/finally so a throw from
  // any malloc, copyToHeap, or the parse call itself frees everything we
  // managed to allocate. Earlier versions allocated and partially populated
  // before entering the try, so a throw from copyToHeap leaked the wasm
  // address back to the heap.
  let sourceAddr = 0;
  let filenameAddr = 0;
  let filenameLen = 0;
  let parseResult = 0;
  try {
    sourceAddr = FlowParserWASM._malloc(sourceBuffer.length + 1);
    if (!sourceAddr) {
      throw new Error('Parser out of memory');
    }
    if (filenameBuffer != null) {
      filenameAddr = FlowParserWASM._malloc(filenameBuffer.length + 1);
      if (!filenameAddr) {
        throw new Error('Parser out of memory');
      }
      copyToHeap(filenameBuffer, filenameAddr);
      filenameLen = filenameBuffer.length + 1;
    }
    copyToHeap(sourceBuffer, sourceAddr);

    // `enableTypes` mirrors OCaml's `types` option, which defaults to true.
    // Fixtures opt out via `types: false` to exercise the no-type-grammar
    // path (e.g. ts_syntax fixtures testing that `as`/`satisfies` are not
    // parsed when types are disabled).
    const enableTypes = options.enableTypes === false ? 0 : 1;
    // `sourceType` is sent to Rust as an integer code:
    //   0 = unspecified / parser default

View on GitHub (pinned to 5c86586199)