facebook/flow · error

hermesParse: invalid source_type={other}; expected 0 (unspec

Error message

hermesParse: invalid source_type={other}; expected 0 (unspecified), 1 (script), or 2 (module).

What it means

hermesParse is the WASM FFI entry point of the Flow parser, taking a long positional argument list. It validates source_type up front and panics for anything outside 0 (unspecified), 1 (script), 2 (module), before touching the source buffer. This guards the FFI boundary against an invalid enum value arriving from the JS bridge.

Source

Thrown at rust_port/crates/flow_parser_wasm/src/lib.rs:122

    source_size: usize,
    source_filename: *const u8,
    source_filename_size: usize,
    enable_components: i32,
    enable_match: i32,
    enable_decorators: i32,
    tokens: i32,
    allow_return_outside: i32,
    assert_operator: i32,
    enable_enums: i32,
    enable_records: i32,
    enable_types: i32,
    source_type: i32,
    enable_types_pragma_detection: i32,
    _enable_types_in_comments: i32,
) -> *mut ParseResult {
    match source_type {
        0..=2 => {}
        other => panic!(
            "hermesParse: invalid source_type={other}; expected 0 (unspecified), \
             1 (script), or 2 (module)."
        ),
    }

    // SAFETY: The JS bridge in flow-parser/oxidized-src/FlowParser.js wraps
    // every call to `hermesParse` in a try/finally that allocates `source`
    // via `_malloc`, copies `source_size` bytes into it, calls this
    // function, and frees the allocation in `finally`. The pointer is
    // therefore valid for `source_size` bytes for the duration of this
    // call. `source_size` is the JS-side `Buffer.length + 1` (UTF-8 source
    // plus a null terminator), so the slice is in-bounds.
    let source_bytes = unsafe { std::slice::from_raw_parts(source, source_size) };
    // Source is null-terminated; exclude the null for parsing
    let source_len = if source_size > 0 { source_size - 1 } else { 0 };
    let source_str = match std::str::from_utf8(&source_bytes[..source_len]) {
        Ok(s) => s,
        Err(_) => {

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Pass one of the three allowed constants: 0, 1, or 2 — use 2 for ES modules and 1 for scripts.
  2. Reinstall so JS and wasm match: rm -rf node_modules && npm ci (or clear the bundler's wasm cache).
  3. Count the positional arguments in your call against the wasm signature; an off-by-one shift silently lands a different value in source_type.
  4. If you extended the enum in JS, rebuild the wasm or stop sending the new value to old binaries.

Example fix

// before
parseResult = FlowParser.parse(source, /* ... */, 3);

// after: 0=unspecified, 1=script, 2=module
parseResult = FlowParser.parse(source, /* ... */, 2);
Defensive patterns

Strategy: validation

Validate before calling

// before calling hermesParse
if (![0, 1, 2].includes(sourceType)) {
  throw new RangeError(`sourceType must be 0|1|2, got ${sourceType}`);
}

Type guard

const isValidSourceType = (t) =>
  Number.isInteger(t) && t >= 0 && t <= 2;

Prevention

When it happens

Trigger: Calling hermesParse(..., source_type) from JS with a value like 3, -1, undefined (coerced to NaN), or a string; most often caused by a JS bridge and wasm binary from different releases — the JS side passes a new enum value the older wasm rejects — or by a shifted positional argument in a hand-written binding.

Common situations: Partial upgrades of the flow-parser npm package where the wasm artifact is stale (bundler cache, mixed lockfile); passing a boolean or a flowconfig-like setting into the source_type slot (it is deep in a ~17-argument positional list); forks that add a new source type in JS without rebuilding the wasm.

Understand the failure class

Background: "invalid argument", "unknown mode", "not supported": invalid enum-like argument errors explained — this error's family across 19 libraries.

Related errors


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