facebook/flow · error

sourceType option must be "script", "module", or…

Error message

sourceType option must be "script", "module", or "unambiguous" if set

What it means

getOptions in the oxidized flow-parser validates sourceType when set: it must be 'script', 'module', or 'unambiguous' ('unambiguous' is then cleared so detection happens during parsing). Any other string — 'commonjs', 'esm', '' — throws before a parse starts.

Solutions

  1. Map module-system names to parser values: 'esm' -> 'module', 'commonjs' -> 'script', auto -> 'unambiguous'.
  2. Omit sourceType entirely if you want the parser default rather than sending '' or null.
  3. Validate/whitelist sourceType at your own API boundary before calling parse().

Example fix

// before
parse(code, {sourceType: pkgType /* 'commonjs' or 'module' from package.json */});

// after
const sourceType = pkgType === 'module' ? 'module' : 'script';
parse(code, {sourceType});
Defensive patterns

Strategy: validation

Validate before calling

const SOURCE_TYPES = new Set(['script', 'module', 'unambiguous']);
function isValidSourceType(v) {
  return v == null || SOURCE_TYPES.has(v);
}

Type guard

function isSourceTypeOption(v) {
  return v == null || v === 'script' || v === 'module' || v === 'unambiguous';
}

Prevention

When it happens

Trigger: parse(code, {sourceType: 'commonjs'}) or other non-enum values, commonly forwarded from user configuration or from tools whose sourceType vocabulary differs (Babel uses 'unambiguous'|'module'|'script', but configs often carry 'commonjs'/'esm' module-system fields that get passed by mistake).

Common situations: Config plumbing where package.json "type" or bundler settings ('commonjs'/'esm') are mapped directly to parser sourceType; typos; passing undefined-via-empty-string defaults.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at packages/flow-parser/oxidized-src/index.js:51

  // results — earlier versions wrote normalized fields back onto `opts`,
  // poisoning subsequent calls.
  const options: ParserOptions = {...DEFAULTS, ...(opts ?? {})};

  // Default to detecting whether to parse Flow syntax by the presence
  // of an @flow pragma.
  if (options.flow !== 'all' && options.flow !== 'detect') {
    throw new Error('flow option must be "all" or "detect"');
  }

  if (options.sourceType === 'unambiguous') {
    // Clear source type so that it will be detected from the contents of the file
    delete options.sourceType;
  } else if (
    options.sourceType != null &&
    options.sourceType !== 'script' &&
    options.sourceType !== 'module'
  ) {
    throw new Error(
      'sourceType option must be "script", "module", or "unambiguous" if set',
    );
  }

  if (options.enableExperimentalComponentSyntax == null) {
    options.enableExperimentalComponentSyntax = true; // Enable by default
  }

  if (options.enableExperimentalFlowMatchSyntax == null) {
    options.enableExperimentalFlowMatchSyntax = true; // Enable by default
  }

  // Record syntax: upstream defaults `enableExperimentalFlowRecordSyntax` to
  // `true`. The fork's WASM cwrap (FlowParser.js) reads `options.enableRecords`
  // — a separate, OCaml-aligned key intentionally mirroring
  // `default_parse_options`. To preserve the upstream-compatible API surface
  // on the outside while keeping the OCaml-aligned key on the WASM boundary,
  // bridge: default the upstream key, then mirror it onto the cwrap key. The

View on GitHub (pinned to 5c86586199)