Debugging Missing @key Fields in Apollo Federation v2

Missing @key fields in a federated graph trigger immediate composition failures or silent runtime entity resolution errors. This guide provides a systematic diagnostic workflow for identifying, isolating, and resolving @key misconfigurations in Apollo Federation v2.

Federation v2 @key Directive Requirements

In Federation v2, the @key directive explicitly defines the primary identifier for an entity, enabling the router to construct cross-subgraph representations. Unlike v1, v2 enforces strict schema validation: every entity must declare at least one @key field. The router uses these fields to route partial queries to the correct subgraph. If a field is omitted from the SDL or lacks the directive, composition fails deterministically. For a complete breakdown of entity mapping mechanics, review the Subgraph Implementation & Entity Resolution architecture guide.

Diagnosing Composition Failures via Rover CLI

Always begin troubleshooting by capturing the exact composition error. Run the following command against your local schema files:

rover supergraph compose --config supergraph.yaml

A missing or malformed @key directive produces a standardized validation payload:

[ERROR] Entity type 'Product' is missing a @key directive. Ensure all entities declare at least one @key field for cross-subgraph resolution.

If the directive exists but references an undefined field, the output shifts to:

[ERROR] Field 'productId' is not defined in the entity type 'Product'.

These logs isolate the failure to a specific subgraph, entity type, and missing field. Cross-reference the output with your local SDL to verify directive placement and field declarations.

Step-by-Step Resolution Workflow

Follow this diagnostic path to resolve composition failures:

  1. Audit the Failing Subgraph SDL: Locate the entity type referenced in the Rover error.
  2. Verify Directive Syntax: Ensure @key is attached directly to the type definition. Use the minimal viable configuration:
type Product @key(fields: "id") {
id: ID!
name: String
price: Float
}

Note: In v2, extend type is used for entities defined in other subgraphs, while type Product @key(fields: "id") is used in the owning subgraph. 3. Validate Field Existence & Type Consistency: The field referenced in @key(fields: "...") must be explicitly declared in the type block. Crucially, scalar types must match exactly across all subgraphs. A mismatch (e.g., ID! in Subgraph A vs String! in Subgraph B) will fail composition. 4. Re-run Composition: Execute rover supergraph compose to validate the schema. 5. Test Entity Resolution: Once composition succeeds, validate runtime behavior using Apollo Sandbox.

Runtime Validation & Reference Resolver Implementation

Successful composition does not guarantee functional entity resolution. You must implement a __resolveReference resolver to fetch the full entity payload when the router requests it.

Minimal Viable Resolver (Node.js/TypeScript):

const resolvers = {
 Product: {
 __resolveReference: async (reference, context) => {
 // 'reference' contains the exact @key fields requested by the router
 const { id } = reference;
 return await db.products.findById(id);
 }
 }
};

Ensure the resolver extracts the @key field from the incoming reference object and queries your data source. For advanced resolver patterns and performance tuning, consult Implementing Entity Resolvers with @key Directives.

Verification Query & Expected Response: Execute a cross-subgraph query to trigger entity resolution:

query {
 topProducts(first: 2) {
 id
 name
 reviews {
 score
 comment
 }
 }
}

Router Trace Expectation:

  • Subgraph A returns [{ id: "1", name: "Laptop" }]
  • Router extracts id: "1" and routes to Subgraph B
  • Subgraph B __resolveReference receives { __typename: "Product", id: "1" }
  • Subgraph B returns { id: "1", reviews: [...] }
  • Router merges payloads and returns the final response.

Monitor Apollo Router logs for __resolveReference execution times. High latency or null returns indicate resolver misconfiguration or missing @key field alignment.

Common Pitfalls & Resolutions

Mistake Root Cause Resolution
Omitting @key on the base subgraph Assuming the router infers identifiers automatically. Explicitly declare @key(fields: "fieldName") on the originating entity type.
Incompatible scalar types for @key fields Defining String in one subgraph and ID in another. Standardize the scalar across all referencing subgraphs (prefer ID!).
@key field omitted from type definition Field used in directive but missing from the SDL block. Ensure the field is explicitly defined with matching casing and type in the type block.
Incorrect @external usage Marking the @key field as @external in the owning subgraph. Only use @external in extending subgraphs. The owning subgraph must define the field natively.

FAQ

Why does Apollo Federation v2 require explicit @key fields for entities?

Federation v2 enforces explicit @key declarations to guarantee deterministic entity resolution across distributed services. This eliminates ambiguity during schema composition and ensures the router can reliably construct entity representations for cross-subgraph queries.

Can I use multiple fields in a single @key directive?

Yes. Federation v2 supports composite keys using the syntax @key(fields: "id version"). The router will use the combined values to uniquely identify the entity across subgraphs.

How do I verify that my reference resolver is correctly using the @key field?

Use the Apollo Sandbox or GraphQL Playground to execute a query that spans multiple subgraphs. Enable router-level logging (--log-level=debug) to trace __resolveReference execution and confirm that the resolver receives the exact @key field payload and returns the expected entity data.

Next Steps

  1. Commit the corrected SDL and re-run rover subgraph publish.
  2. Enable distributed tracing in your Apollo Router to monitor entity resolution latency.
  3. Implement automated schema checks in your CI/CD pipeline using rover subgraph check to catch @key violations before deployment.