Skip to content

A schema with all deprecated elements removed must itself be valid - #1231

Open
benjie wants to merge 1 commit into
mainfrom
undeprecated-schema-is-valid
Open

benjie wants to merge 1 commit into
mainfrom
undeprecated-schema-is-valid

Conversation

@benjie

@benjie benjie commented Jun 10, 2026

Copy link
Copy Markdown
Member

As a precursor to deprecating other schema elements (object types, etc), I figured it would be best to simplify the rule: the schema with all deprecated elements removed should itself be valid. This is a breaking change for servers currently (could mark a previously valid schema as invalid), but solvable in a non-breaking way by removing @deprecated directives, or (once they are supported) adding @deprecated to object types and other positions. It's non-breaking for clients.

This also aligns with #1230 wherein the schema with all deprecated elements removed is represented via { __schema(includeDeprecated: false) { ... } }.

@benjie benjie added the 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md) label Jun 10, 2026
@benjie

benjie commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

cc @fotoetienne

@netlify

netlify Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploy Preview for graphql-spec-draft ready!

Name Link
🔨 Latest commit ac84f6e
🔍 Latest deploy log https://app.netlify.com/projects/graphql-spec-draft/deploys/6a293fdcee4ac800085e4d30
😎 Deploy Preview https://deploy-preview-1231--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.

@fotoetienne

Copy link
Copy Markdown
Contributor

Should this go along with a change to allow empty objects?

@benjie

benjie commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

@fotoetienne

fotoetienne commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Yes! Should #1228 be a prereq for #1231?

@benjie benjie added the 🚀 Next Stage? This RFC believes it is ready for the next stage label Jun 18, 2026
@benjie

benjie commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

I don't think it needs to be, but in an ideal world they'd all be merged together.

@leebyron leebyron added 💡 Proposal (RFC 1) RFC Stage 1 (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 labels Jul 2, 2026
2. Let {implementedFieldType} be the return type of {implementedField}.
3. {IsValidImplementationFieldType(fieldType, implementedFieldType)} must
be {true}.
6. If {field} is deprecated then {implementedField} must also be deprecated.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

imho we should leave this in place though as an implementation of the new definition you've added above?

I don't think the spec should leave various ways in which the subset-is-valid needs to be looked out for

separately, I think removing this actually says something else-- that an interface field being deprecated may differ from the deprecation status of an implemented field? -- that could be a separate proposal if that's what we want to explore

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

we should leave this in place though as an implementation of the new definition you've added

I'm not convinced the redundancy gives us enough value to justify it. One of the reasons that deprecating things (object types, etc) is so hard to do spec-wise is because of all the knock-on consequences (especially with the "at least one field" rules we have, until #1228/etc are merged).

Removing all of that and replacing with "schema with all deprecated elements removed must be valid" is much much simpler; and it's really easy to build into a GraphQL implementation without having to implement each and every one of the rules that govern it individually:

function assertSchemaIsValid(schema) {
  // ... all other rules ...
  
  const reducedSchema = removeDeprecatedElements(schema)
  if (reducedSchema !== schema) assertSchemaIsValid(reducedSchema);
}

Libraries might need to implement more logic to make sure that violations raise useful error messages, but since the error messages aren't specified currently I think this is a fair trade-off to make?

separately, I think removing this actually says something else

I had to read it carefully, but I don't think so - implementedType is the interface:

interface ImplementedType {
  id: ID!
  f: Int # implementedField
}
type Query implements ImplementedType {
  id: ID!
  f: Int # field
}

This rule says: if field (Query.f) is deprecated, then implementedField (ImplementedType.f) must also be deprecated; i.e. the following is invalid:

interface ImplementedType {
  id: ID!
  f: Int
}
type Query implements ImplementedType {
  id: ID!
  f: Int @deprecated(reason: "...")
}

If we remove the deprecated elements (Query.f) then the resulting schema is invalid, matching the overarching rule - i.e. we're saying the same thing: schema with deprecated elements removed must be valid.

Removing this rule would remove this potential confusion.

Comment on lines +139 to +140
If a GraphQL schema contains any deprecated _schema element_, a copy of the
schema that omits all deprecated _schema element_ must itself be valid.

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.

Maybe: "A copy of a GraphQL schema that omits every deprecated schema element must itself be valid."

A schema with no deprecated elements will be trivially valid. Also making sure _schema element_ is pluralized correctly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I added the more verbose wording to avoid infinite loops such as const isValid = schema => otherValidationRules(schema) && isValid(removeDeprecated(schema)). We can't (currently) pluralize keywords because it will break spec-md lookup.

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

Labels

💡 Proposal (RFC 1) RFC Stage 1 (See CONTRIBUTING.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants