Skip to content

SchemaTransformer.transformSchema produces schema with dangling reference to deleted type #4133

@alf

Description

@alf

Describe the bug
We've implemented a visitor that prunes our schema based on the presence of a directive.
This has worked well until quite recently, but has suddenly started failing with graphql.AssertException: Assert type Rom not found in schema.

I've analyzed the problem and reduced the schema and our visitor down to the minimal needed to reproduce the issue. Note that our actual implementation also handles other schema elements, but I don't think this is relevant for the issue at hand.

To Reproduce

Given the following schema, our visitor crashes with AssertException:

directive @remove on FIELD_DEFINITION

type Query {
  rental: Rental @remove
  customer: Customer
}

type Store {
  inventory: Inventory @remove
}

type Inventory {
  store: Store @remove
}

type Customer {
  rental: Rental
  payment: Payment @remove
}

type Payment {
  inventory: Inventory @remove
}

type Rental {
  id: ID
  customer: Customer @remove
}

Our visitor is defined as follows:

    class SchemaPruningVisitor extends GraphQLTypeVisitorStub {
        @Override
        public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition node, TraverserContext<GraphQLSchemaElement> context) {
            if (node.hasAppliedDirective("remove")) {
                return deleteNode(context);
            }

            return CONTINUE;
        }

        @Override
        public TraversalControl visitGraphQLObjectType(GraphQLObjectType node, TraverserContext<GraphQLSchemaElement> context) {
            if (node.getFields().stream().allMatch(field -> field.hasAppliedDirective("remove"))) {
                return deleteNode(context);
            }

            return CONTINUE;
        }
    }

Interesting observation

Note that if we flip the order of the Query.rental and Query.customer fields then our visitor no longer crashes and produces the schema we expect:

type Query {
  customer: Customer
}

type Customer {
  rental: Rental
}

type Rental {
  id: ID
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    keep-openTells Stale Bot to keep PRs and issues open

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions