__typename is not valid at subscription root
At a glance​
- Identifier: #776
- Stage: RFC3: Accepted
- Champion: @benjie
- PR: __typename is not valid at subscription root
- Related:
- #806 (__typename should be valid at subscription root)
Timeline​
- Added to 2021-05-13 WG agenda
- Mentioned in 2021-05-13 WG notes
- Commit pushed: Update Section 5 -- Validation.md on 2021-04-15 by @leebyron
- Added to 2021-01-07 WG agenda
- Mentioned in 2021-01-07 WG notes
- Added to 2020-12-03 WG agenda
- Mentioned in 2020-12-03 WG notes
- 4 commits pushed on 2020-11-25:
- Added to 2020-10-01 WG agenda
- Mentioned in 2020-10-01 WG notes
- Spec PR created on 2020-09-14 by benjie
- Commit pushed: __typename is not valid at subscription root on 2020-09-14 by @benjie
I'm writing up some of the GraphQL "query ambiguity" work currently and noticed this issue in the spec. In the case of a subscription it seems that
subscription {
__typename
}does not correctly get evaluated by the reference implementation during subscriptions (though you can query it with
graphql(...)you can't access it viasubscribe(...)). It doesn't really make sense to request__typenamehere since it's not ever going to change during the life of the schema, and subscriptions only support one root-level field, however I thought it was worth highlighting.Reproduction with GraphQL-js (toggle which
docis commented to see a functioning subscription):const {
GraphQLSchema,
GraphQLObjectType,
GraphQLInt,
GraphQLFloat,
parse,
validate,
subscribe,
} = require("graphql");
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
async function* everySecond() {
for (let i = 0; i < 1000; i++) {
yield i;
await sleep(1000);
}
}
const Query = new GraphQLObjectType({
name: "Query",
fields: {
a: {
type: GraphQLInt,
},
},
});
const Subscription = new GraphQLObjectType({
name: "Subscription",
fields: {
ts: {
type: GraphQLFloat,
subscribe() {
return everySecond();
},
resolve() {
return Date.now();
},
},
},
});
const schema = new GraphQLSchema({
query: Query,
subscription: Subscription,
});
async function main() {
const doc = parse("subscription { __typename }");
// const doc = parse("subscription { ts }");
const errors = validate(schema, doc);
if (errors && errors.length) {
console.dir(errors);
throw new Error("Errors occurred");
}
const result = await subscribe(schema, doc);
console.dir(result);
for await (const r of result) {
console.dir(r);
}
}
main().catch(e => {
console.dir(e);
process.exit(1);
});Produces this error:
Error: Subscription field must return Async Iterable. Received: undefined
at [...]/node_modules/graphql/subscription/subscribe.js:169:13
at async main ([...]/test.js:57:18)