Cannot query field X on type Y after schema rollback
0 reputation · 08 Aug 2021, 18:53 UTC
0 reputation · 08 Aug 2021, 18:53 UTC
When a GraphQL server removes or alters a field, existing queries that rely on the old definition produce the validation error Cannot query field X on type Y at runtime. This breaks clients that have cached the previous schema.
Design a rollback‑safe deployment strategy that allows in‑flight requests to succeed while maintaining a stable API surface for clients during a schema change.
34775 reputation · 09 Aug 2021, 02:09 UTC
The most efficient way to expose both the old and new schema definitions during a rollback window is to build a single executable schema that contains both versions of the type definitions while sharing a single resolver map. This avoids duplicating resolver logic and lets you switch between schemas with a lightweight feature flag or request header.
GraphQLSchema objects in memory and select one per request.The validation error Cannot query field X on type Y appears when a client sends a query that expects a field that has been removed or altered in the newly deployed schema, while the client’s cached introspection still advertises the old field.
@deprecated directive to the old field, optionally adding a custom directive such as @removedInVersion("2.0") to signal pending removal.makeExecutableSchema (Apollo Server) or to SchemaGenerator.newSchema (GraphQL‑Java). The resolver logic is written once and attached to the unified schema.const unifiedSchema = makeExecutableSchema({
typeDefs: /* SDL with old + new fields and directives */,
resolvers: sharedResolvers
});
GraphQLSchema instance based on a request header (e.g., X-GraphQL-Version: legacy) or a feature flag.new schema by default.function getSchema(req) {
return req.headers['x-graphql-version'] === 'legacy' ? legacySchema : currentSchema;
}
@deprecated directive makes isDeprecated:true appear in introspection, and the custom directive can be read by tooling to show a version‑based warning.isDeprecated:true and the custom directive.GraphQLSchema objects; switching via context is straightforward. Memory overhead is roughly linear with the number of schemas kept.SchemaGenerator can rebuild a schema quickly; keeping two schemas in memory is possible, with similar linear memory cost. Hot‑swap is achieved by swapping the GraphQLSchema reference used by the graphql object.Do you have the ability to add a custom header or query parameter to route requests to the appropriate schema version? If not, the recommendation would shift to using a URL‑based endpoint (e.g., /graphql-legacy) instead of a header.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.