facebook/relay · error

Expected @{} directive to have a path argument

Error message

Expected @{} directive to have a path argument

What it means

During typegen, transform_graphql_scalar_type processes fields annotated with a custom scalar directive. When the directive is present but lacks the required path argument (the import path of the JS type module), the compiler panics — the @customScalar directive contract requires both path and export_name.

Source

Thrown at compiler/crates/relay-typegen/src/visit.rs:2297

    }
}

fn transform_graphql_scalar_type(
    typegen_context: &'_ TypegenContext<'_>,
    scalar: ScalarID,
    custom_scalars: &mut CustomScalarsImports,
) -> AST {
    let scalar_definition = typegen_context.schema.scalar(scalar);
    let scalar_name = scalar_definition.name;
    if let Some(directive) = scalar_definition
        .directives
        .named(DirectiveName(*CUSTOM_SCALAR_DIRECTIVE_NAME))
    {
        let path = directive
            .arguments
            .named(ArgumentName(*PATH_CUSTOM_SCALAR_ARGUMENT_NAME))
            .unwrap_or_else(|| {
                panic!(
                    "Expected @{} directive to have a path argument",
                    *CUSTOM_SCALAR_DIRECTIVE_NAME
                )
            })
            .expect_string_literal();

        let import_path = typegen_context.project_config.js_module_import_identifier(
            &typegen_context
                .project_config
                .artifact_path_for_definition(typegen_context.definition_source_location),
            &PathBuf::from(path.lookup()),
        );

        let export_name = directive
            .arguments
            .named(ArgumentName(*EXPORT_NAME_CUSTOM_SCALAR_ARGUMENT_NAME))
            .unwrap_or_else(|| {
                panic!(

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Add the path argument to the custom scalar directive pointing at the module exporting the JS type.
  2. Ensure both path and export_name arguments are present together.
  3. Regenerate the annotation with a current version of the tooling.
  4. Check the expected argument name matches PATH_CUSTOM_SCALAR_ARGUMENT_NAME (exact spelling).

Example fix

// before
@customScalar(export_name: "MyScalarType")
// after
@customScalar(path: "./src/types/MyScalarType.ts", export_name: "MyScalarType")
Defensive patterns

Strategy: validation

Validate before calling

// validate custom scalar annotations have both path and export_name
if (hasCustomScalarDirective(node) && !getArg(node, 'path')) throw new Error('custom scalar directive requires a path argument');

Type guard

function hasPathArg(directive) { return directive.arguments?.some(a => a.name.value === 'path'); }

Prevention

When it happens

Trigger: A @customScalar (CUSTOM_SCALAR_DIRECTIVE_NAME) annotation applied without a path argument, encountered while transforming scalar types in visit.rs during typegen.

Common situations: Hand-written or tool-generated scalar annotations missing the path argument; renaming/refactoring that dropped the argument; inconsistent versions between the tool emitting the directive and the compiler.

Related errors


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