facebook/flow · error

flow option must be "all" or "detect"

Error message

flow option must be "all" or "detect"

What it means

The oxidized flow-parser's getOptions validates that the `flow` option is exactly 'all' or 'detect' (after spreading defaults, so an unset value defaults to 'detect'). Unlike the older hermes-parser JS API, booleans and 'none' are not accepted, and any other value throws immediately before parsing.

Solutions

  1. Use flow: 'all' to always parse Flow syntax, or 'detect' (default) to parse only files with an @flow pragma.
  2. To get the old 'none' behavior, use 'detect' and remove/ignore the @flow pragma so the file parses as plain JS.
  3. Normalize options at your API boundary: reject or coerce unknown `flow` values before they reach parse().

Example fix

// before
parse(code, {flow: false}); // or {flow: 'none'}

// after
parse(code, {flow: 'detect'}); // and ensure the file has no @flow pragma
Defensive patterns

Strategy: validation

Validate before calling

// Normalize before calling parse
function normalizeFlowOption(value) {
  if (value === true) return 'all';
  if (value === false || value === 'none') return 'detect'; // ensure no @flow pragma for none-semantics
  if (value === 'all' || value === 'detect') return value;
  throw new TypeError(`flow option must be "all" or "detect", got ${JSON.stringify(value)}`);
}

Type guard

function isFlowOption(v) {
  return v === 'all' || v === 'detect';
}

Prevention

When it happens

Trigger: Calling parse(code, {flow: false}), {flow: true}, or {flow: 'none'} — options that hermes-parser/babel-lineage parsers accepted. Migration code passing legacy option shapes into flow-parser's parse() hits this on the first call.

Common situations: Migrating from hermes-parser or other parsers where flow syntax enablement was boolean or included 'none'; config normalization layers that pass through user-supplied strings unchecked.

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/9346f202169fd064. Report an issue: GitHub.

Appendix: source

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

import * as TransformRecordSyntax from './estree/TransformRecordSyntax';
import * as StripFlowTypesForBabel from './estree/StripFlowTypesForBabel';
import * as StripFlowTypes from './estree/StripFlowTypes';

const DEFAULTS: {flow: 'detect'} = {
  flow: 'detect',
};

function getOptions(opts?: ParserOptions): ParserOptions {
  // Always build a fresh object so we never mutate the caller's input.
  // Repeated calls with the same `opts` reference must produce identical
  // 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
  }

View on GitHub (pinned to 5c86586199)