Skip to content

Test: Missing subscription field should not be an "internal error" #1106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 6, 2017

Conversation

leebyron
Copy link
Contributor

@leebyron leebyron commented Dec 2, 2017

Test: Missing subscription field should not be an "internal error"

A remaining issue with subscriptions is attempting to subscribe to a missing field. The existing implementation creates an internal error which is an improper blame since there is no possibility to fix it internally - it is an issue with the query.

Since there is no clear consistent behavior relative to query/mutation operations (which simply skip over unknown fields), and the corner-case where this occurs should deal with the error - this changes the internal error to an external yielded GraphQL error.

Note: we still require a spec change since there is an ambiguity of this exact scenario.

Copy link
Contributor

@robzhu robzhu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When trying to execute a subscription with an invalid selection set, I think we should throw when attempting to create the subscription.

EDIT: I used "throw" too loosely. I meant in accordance with how we want to handle 400-class errors elsewhere. My impressions is that returning an emptyAsyncIterator feels too subtle for an error case.

@@ -347,7 +346,7 @@ describe('Subscription Initialization Phase', () => {
);
});

it('throws an error for unknown root field', async () => {
it('unknown field should result in closed subscription', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think asking for an unknown field is a 400-class error code (something about the request was malformed). In that case, I think the await createSubscription call should throw.

My reasonings is that if we don't throw there, we'll have a subscription that is in the closed state, which does not communicate that the request was invalid or what was wrong with it.

);

if (!fieldDef) {
return resolve(emptyAsyncIterator());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't feel like the right return value for a missing field case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be a better one? Presuming an error becomes the domain of a validation step, we should produce something

Copy link
Contributor

@robzhu robzhu Dec 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In https://github.com/facebook/graphql/blob/master/spec/Section%206%20--%20Execution.md#executing-requests we describe Subscribe as the async variant of ExecuteQuery. For ExecuteQuery, the spec says, "Return an unordered map containing {data} and {errors}."while Subscribe says Return {responseStream}.. Perhaps we should update these to be more similar, for example, 'Subscribe` could resolve to an unordered map of {responseStream} and {errors}.

@leebyron
Copy link
Contributor Author

leebyron commented Dec 4, 2017

Also remember that "subscribe" is the second half of a presumed "validate & subscribe" path. I think the missing piece is a validation rule that a subscription is well-formed.

There is symmetry if my proposed behavior to execute which skips over unknown fields such that { unknownField } yields {}.

My suggestion here is that the "subscribe" operation is the wrong place for this error, it should instead be caught earlier during validation, and instead this operation should be durable to the malformed input

@leebyron
Copy link
Contributor Author

leebyron commented Dec 5, 2017

http://facebook.github.io/graphql/draft/#sec-Subscription-Operation-Definitions seems to handle this case, validation errors are typically reported as 400-level.

Perhaps we should update these to be more similar, for example, 'Subscribe` could resolve to an unordered map of {responseStream} and {errors}.

I think the flow types we've defined more closely refer to a responseStream or a single error response payload

@leebyron leebyron force-pushed the missing-subscription-field branch 3 times, most recently from 557a773 to e09e823 Compare December 6, 2017 18:40
A remaining issue with subscriptions is attempting to subscribe to a missing field. The existing implementation creates an internal error which is an improper blame since there is no possibility to fix it internally - it is an issue with the query.

Since there is no clear consistent behavior relative to query/mutation operations (which simply skip over unknown fields), and the corner-case where this occurs should deal with the error - this changes the internal error to an external yielded GraphQL error.

Note: we still require a spec change since there is an ambiguity of this exact scenario.
@leebyron leebyron force-pushed the missing-subscription-field branch from e09e823 to aac2a5e Compare December 6, 2017 19:15
@leebyron leebyron merged commit f2c96b0 into master Dec 6, 2017
@leebyron leebyron deleted the missing-subscription-field branch December 6, 2017 19:48
@leebyron
Copy link
Contributor Author

leebyron commented Dec 6, 2017

Updated description and commit to reflect "400" level error rather than current "500" level error after offline review with @robzhu

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants