Skip to content

Allow empty selection sets - #1227

Merged
leebyron merged 3 commits into
mainfrom
empty-selection-sets
Sep 17, 2026
Merged

leebyron merged 3 commits into
mainfrom
empty-selection-sets

Conversation

@benjie

@benjie benjie commented May 23, 2026

Copy link
Copy Markdown
Member

Since 2015 we've required selection sets to contain at least one field; however it's always been possible to have an empty object returned:

type A { a: Int }
type B { b: Int }
union U = A | B
type Query { u: U }

query {
  u {
    ... on A { __typename }
  }
}

Here, if u returns type B the result will be {"data":{"u":{}}} - i.e. an empty object.

GraphQL clients are getting smarter and smarter, and it's common to have client-side extensions such as Apollo's @client, Relay Resolvers or @mock'd fields. In all of these cases, any selections of these fields need to be removed before the document is sent to the server. But what happens when all the fields in the selection set are to be removed?

  query LaunchDetails($launchId: ID!) {
    launch(id: $launchId) {
      isInCart @client
      site @client
    }
  }

There are many options (add __typename, remove launch, throw error, ...), but the safest solution is to allow the selection set to be empty. Hence, this PR.

@netlify

netlify Bot commented May 23, 2026

Copy link
Copy Markdown

Deploy Preview for graphql-spec-draft ready!

Name Link
🔨 Latest commit e10dca1
🔍 Latest deploy log https://app.netlify.com/projects/graphql-spec-draft/deploys/6a9a9c8ff4b52d0008c09281
😎 Deploy Preview https://deploy-preview-1227--graphql-spec-draft.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@benjie benjie added 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md) 🚀 Next Stage? This RFC believes it is ready for the next stage labels May 23, 2026

@martinbonnin martinbonnin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment thread spec/Appendix B -- Notation Conventions.md Outdated
@benjie
benjie force-pushed the empty-selection-sets branch from 8c13477 to 220e8d4 Compare May 25, 2026 11:37

@jerelmiller jerelmiller left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💯

Comment thread spec/Section 5 -- Validation.md

@magicmark magicmark left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice :)

@leebyron leebyron added 💡 Proposal (RFC 1) RFC Stage 1 (See CONTRIBUTING.md) 📄 Draft (RFC 2) RFC Stage 2 (See CONTRIBUTING.md) and removed 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md) 🚀 Next Stage? This RFC believes it is ready for the next stage 💡 Proposal (RFC 1) RFC Stage 1 (See CONTRIBUTING.md) labels Jul 2, 2026
@benjie benjie added 🏁 Accepted (RFC 3) RFC Stage 3 (See CONTRIBUTING.md) and removed 📄 Draft (RFC 2) RFC Stage 2 (See CONTRIBUTING.md) labels Sep 3, 2026
@benjie

benjie commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

I believe this is ready to merge, pending @yaacovCR's feedback on the GraphQL.js PR:

@yaacovCR

yaacovCR commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

If we're going to merge this, I think we can takeoff the experimental label on the associated PR?

@martinbonnin

Copy link
Copy Markdown
Contributor

If we're going to merge this, I think we can takeoff the experimental label on the associated PR?

Excellent observation @yaacovCR. We can even probably drop the parameter altogether?

@martinbonnin

Copy link
Copy Markdown
Contributor

I made another version of the PR if we decide to expedite this:

My preference goes to "without experimental flag". Less complexity is better.

@benjie

benjie commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

I personally would keep the flag until next semver major, even if you default to enabling the feature. Reason: their security systems might not be set up to handle queries like this; consider:

{
  user {
    a: friends {}
    b: friends {}
    c: friends {}
  }
}

if they're using complexity cost that multiples expected list length by selection set cost, and selection set cost is zero because there's no fields (previously not possible), it might have an impact on their security. (The IBM cost spec does not suffer from this AFAIK, but there are lots of models of query cost in the wild.)

There may be other such concerns that we're not yet aware of, so giving people a way to opt out until v18 does not seem unwise.

@martinbonnin

martinbonnin commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

giving people a way to opt out until v18 does not seem unwise.

Works for me. All in all:

  • drop experimental: experimentalEmptySelectionsSets -> allowEmptySelectionSets
  • default to true
  • make it deprecated
    ?

I have updated the PR in that direction. Let me know if something else is preferred.

@benjie

benjie commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

We'll merge this during the secondary WG on Thursday 17th unless anyone has reservations (express them now!)

@benjie benjie added the 🚀 Next Stage? This RFC believes it is ready for the next stage label Sep 10, 2026
@leebyron
leebyron merged commit b4a3a20 into main Sep 17, 2026
9 checks passed
@leebyron
leebyron deleted the empty-selection-sets branch September 17, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🏁 Accepted (RFC 3) RFC Stage 3 (See CONTRIBUTING.md) 🚀 Next Stage? This RFC believes it is ready for the next stage

Projects

None yet

Development

Successfully merging this pull request may close these issues.