facebook/relay · error

Expected operation artifact to have an `id`. Ensure a `persi

Error message

Expected operation artifact to have an `id`. Ensure a `persistConfig` is setup for the current project.

What it means

generate_preloadable_query_parameters_artifact emits the `<query>$parameters.js` preloadable artifact, which requires the operation's persisted id. The id comes from id_and_text_hash, populated only when persistConfig/persisted-queries is set up; if it's None the expect panics instructing the developer to configure persistence.

Source

Thrown at compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs:271

            typegen_operation: operations.expect_typegen(),
            source_hash,
            text,
            id_and_text_hash: None,
        },
        source_file: normalization.name.location.source_location(),
    }
}

pub fn generate_preloadable_query_parameters_artifact(
    project_config: &ProjectConfig,
    normalization: &Arc<OperationDefinition>,
    id_and_text_hash: &Option<QueryID>,
    source_keys: Vec<ArtifactSourceKey>,
    source_file: SourceLocationKey,
) -> Artifact {
    let query_id = id_and_text_hash
        .clone()
        .expect("Expected operation artifact to have an `id`. Ensure a `persistConfig` is setup for the current project.");

    let artifact_name = normalization.name.item.0.to_string() + "$parameters";

    Artifact {
        artifact_source_keys: source_keys,
        path: project_config.path_for_language_specific_artifact(source_file, artifact_name),
        content: ArtifactContent::PreloadableQueryParameters {
            normalization_operation: Arc::clone(normalization),
            query_id,
        },
        source_file,
    }
}

fn generate_updatable_query_artifact(
    artifact_source: ArtifactSourceKey,
    project_config: &ProjectConfig,
    operations: &OperationGroup<'_>,

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Set up persistConfig in the project's relay config so operation ids are generated before artifacts
  2. Ensure the persist step (id generation) runs before generate_artifacts, or run `relay persist-operations` as part of the build
  3. If persistence is not intended, disable preloadable query artifact generation for the project

Example fix

// before (relay.config.js)
module.exports = { src: "./src", schema: "./schema.graphql" };
// after
module.exports = {
  src: "./src",
  schema: "./schema.graphql",
  persistConfig: { type: "file", file: "./queryMap.json" },
};
Defensive patterns

Strategy: validation

Validate before calling

const cfg = require('./relay.config.js');
if (cfg.preloadableQueries && !cfg.persistConfig) {
  throw new Error('Preloadable queries require persistConfig for persisted operation ids');
}

Try / catch

try {
  await relay(['build']);
} catch (e) {
  if (/Expected operation artifact to have an `id`/.test(e.message)) {
    console.error('Add persistConfig to relay.config.js or disable preloadable query artifacts.');
  } else throw e;
}

Prevention

When it happens

Trigger: Enabling preloadable query generation (persisted queries) for a project whose relay config lacks persistConfig, so operations have text/hash but no persisted id at artifact generation time.

Common situations: Adding preloadable queries to an app that never configured persistConfig (e.g. @queryPersisted or a custom persister); migrating a project to persisted queries without setting up the persist pipeline; build generators expecting ids before running the persist step.

Related errors


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