facebook/relay · error

Babel state is missing expected file name

Error message

Babel state is missing expected file name

What it means

getRelativeImportPath needs the current source file's path (state.file.opts.filename) to compute a relative require path from the file to the generated artifact directory. If state.file is null the Babel state is malformed, so the plugin cannot determine where the importing file lives and throws. This is an environment/tooling failure, not a user GraphQL mistake.

Source

Thrown at packages/babel-plugin-relay/compileGraphQLTag.js:247

    t.memberExpression(t.identifier('console'), t.identifier('error')),
    [
      t.stringLiteral(
        `The definition of '${definitionName}' appears to have changed. Run ` +
          '`' +
          buildCommand +
          '` to update the generated files to receive the expected data.',
      ),
    ],
  );
}

function getRelativeImportPath(
  state: BabelState,
  artifactDirectory: string,
  fileToRequire: string,
): string {
  if (state.file == null) {
    throw new Error('Babel state is missing expected file name');
  }
  const filename = state.file.opts.filename;

  const relative = relativePath(
    dirname(filename),
    resolvePath(artifactDirectory),
  );

  const relativeReference =
    relative.length === 0 || !relative.startsWith('.') ? './' : '';

  return relativeReference + joinPath(relative, fileToRequire);
}

module.exports = compileGraphQLTag;

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Ensure transforms run through @babel/core's normal pipeline so state.file is populated
  2. If invoking programmatically, construct a proper state including file and file.opts.filename
  3. Update babel-plugin-relay and @babel/core to compatible versions
  4. Check other Babel plugins that mutate or strip state.file earlier in the plugin list

Example fix

// before (custom transform with bare state)
plugin({ types: t }, { file: null });

// after (transform via @babel/core)
require('@babel/core').transform(code, {
  filename: '/project/src/Component.js',
  plugins: ['babel-plugin-relay'],
});
Defensive patterns

Strategy: validation

Validate before calling

function assertBabelStateHasFile(state) {
  if (!state || !state.file || !state.file.opts || !state.file.opts.filename) {
    throw new Error('Babel state must include file.opts.filename for babel-plugin-relay');
  }
}

Type guard

const hasFileState = (state) =>
  !!state && !!state.file && !!state.file.opts && typeof state.file.opts.filename === 'string';

Prevention

When it happens

Trigger: Babel invokes the plugin with a state lacking state.file — e.g. custom transform scripts calling the plugin programmatically, some plugin-ordering or caching setups, or tools that fabricate a minimal state without file metadata.

Common situations: Custom Babel wrappers or AST transformers (e.g. codegen tools) that call the plugin with a synthetic state; newer/older Babel versions where state.file shape changed; running transforms outside the normal @babel/core pipeline.

Related errors


AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02). Data as JSON: /api/errors/7070b596d8dd1143. Report an issue: GitHub.