__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__typename
here 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
doc
is 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)