graphql / graphiql

GraphiQL & the GraphQL LSP Reference Ecosystem for building browser & IDE tools.
MIT License
16.09k stars 1.72k forks source link

[graphiql] without the new content type value in introspection headers, introspection can fail with more strictly spec compliant frameworks #3460

Open martinformi opened 12 months ago

martinformi commented 12 months ago

Is there an existing issue for this?

Current Behavior

I am using graphiql with spring-boot-graphql-starter, however I am getting an error even with the simple schema. Can you please verify what is wrong with the response from introspection? Thank you.

Error:

{
  "errors": [
    {
      "message": "Introspection result missing interfaces: { kind: \"OBJECT\", name: \"Deployment\", fields: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 5 more items] }.",
      "stack": "Error: Introspection result missing interfaces: { kind: \"OBJECT\", name: \"Deployment\", fields: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 5 more items] }.\n    at buildImplementationsList (https://unpkg.com/graphiql/graphiql.min.js:33298:13)\n    at interfaces (https://unpkg.com/graphiql/graphiql.min.js:33306:25)\n    at resolveReadonlyArrayThunk (https://unpkg.com/graphiql/graphiql.min.js:29728:40)\n    at defineInterfaces (https://unpkg.com/graphiql/graphiql.min.js:29908:22)\n    at GraphQLObjectType._interfaces (https://unpkg.com/graphiql/graphiql.min.js:29868:30)\n    at GraphQLObjectType.getInterfaces (https://unpkg.com/graphiql/graphiql.min.js:29882:31)\n    at collectReferencedTypes (https://unpkg.com/graphiql/graphiql.min.js:32130:45)\n    at new GraphQLSchema (https://unpkg.com/graphiql/graphiql.min.js:31973:9)\n    at Object.buildClientSchema (https://unpkg.com/graphiql/graphiql.min.js:33212:10)\n    at https://unpkg.com/graphiql/graphiql.min.js:64435:23"
    }
  ]
}

Instrospected schema:

{
    "data": {
        "__schema": {
            "queryType": {
                "name": "Query"
            },
            "types": [
                {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "description": "Built-in Boolean"
                },
                {
                    "kind": "OBJECT",
                    "name": "Query",
                    "fields": [
                        {
                            "name": "getAll",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "SCALAR",
                    "name": "String",
                    "description": "Built-in String"
                },
                {
                    "kind": "OBJECT",
                    "name": "__Directive",
                    "fields": [
                        {
                            "name": "name",
                            "description": "The __Directive type represents a Directive that a server supports.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "String"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "description",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "isRepeatable",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "Boolean"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "locations",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "LIST",
                                    "ofType": {
                                        "kind": "NON_NULL",
                                        "ofType": {
                                            "kind": "ENUM",
                                            "name": "__DirectiveLocation"
                                        }
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "args",
                            "args": [
                                {
                                    "name": "includeDeprecated",
                                    "type": {
                                        "kind": "SCALAR",
                                        "name": "Boolean"
                                    },
                                    "defaultValue": "false"
                                }
                            ],
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "LIST",
                                    "ofType": {
                                        "kind": "NON_NULL",
                                        "ofType": {
                                            "kind": "OBJECT",
                                            "name": "__InputValue"
                                        }
                                    }
                                }
                            },
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "ENUM",
                    "name": "__DirectiveLocation",
                    "description": "An enum describing valid locations where a directive can be placed",
                    "enumValues": [
                        {
                            "name": "QUERY",
                            "description": "Indicates the directive is valid on queries.",
                            "isDeprecated": false
                        },
                        {
                            "name": "MUTATION",
                            "description": "Indicates the directive is valid on mutations.",
                            "isDeprecated": false
                        },
                        {
                            "name": "SUBSCRIPTION",
                            "description": "Indicates the directive is valid on subscriptions.",
                            "isDeprecated": false
                        },
                        {
                            "name": "FIELD",
                            "description": "Indicates the directive is valid on fields.",
                            "isDeprecated": false
                        },
                        {
                            "name": "FRAGMENT_DEFINITION",
                            "description": "Indicates the directive is valid on fragment definitions.",
                            "isDeprecated": false
                        },
                        {
                            "name": "FRAGMENT_SPREAD",
                            "description": "Indicates the directive is valid on fragment spreads.",
                            "isDeprecated": false
                        },
                        {
                            "name": "INLINE_FRAGMENT",
                            "description": "Indicates the directive is valid on inline fragments.",
                            "isDeprecated": false
                        },
                        {
                            "name": "VARIABLE_DEFINITION",
                            "description": "Indicates the directive is valid on variable definitions.",
                            "isDeprecated": false
                        },
                        {
                            "name": "SCHEMA",
                            "description": "Indicates the directive is valid on a schema SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "SCALAR",
                            "description": "Indicates the directive is valid on a scalar SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "OBJECT",
                            "description": "Indicates the directive is valid on an object SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "FIELD_DEFINITION",
                            "description": "Indicates the directive is valid on a field SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "ARGUMENT_DEFINITION",
                            "description": "Indicates the directive is valid on a field argument SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "INTERFACE",
                            "description": "Indicates the directive is valid on an interface SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "UNION",
                            "description": "Indicates the directive is valid on an union SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "ENUM",
                            "description": "Indicates the directive is valid on an enum SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "ENUM_VALUE",
                            "description": "Indicates the directive is valid on an enum value SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "INPUT_OBJECT",
                            "description": "Indicates the directive is valid on an input object SDL definition.",
                            "isDeprecated": false
                        },
                        {
                            "name": "INPUT_FIELD_DEFINITION",
                            "description": "Indicates the directive is valid on an input object field SDL definition.",
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "OBJECT",
                    "name": "__EnumValue",
                    "fields": [
                        {
                            "name": "name",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "String"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "description",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "isDeprecated",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "Boolean"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "deprecationReason",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "OBJECT",
                    "name": "__Field",
                    "fields": [
                        {
                            "name": "name",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "String"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "description",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "args",
                            "args": [
                                {
                                    "name": "includeDeprecated",
                                    "type": {
                                        "kind": "SCALAR",
                                        "name": "Boolean"
                                    },
                                    "defaultValue": "false"
                                }
                            ],
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "LIST",
                                    "ofType": {
                                        "kind": "NON_NULL",
                                        "ofType": {
                                            "kind": "OBJECT",
                                            "name": "__InputValue"
                                        }
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "type",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "OBJECT",
                                    "name": "__Type"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "isDeprecated",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "Boolean"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "deprecationReason",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "OBJECT",
                    "name": "__InputValue",
                    "fields": [
                        {
                            "name": "name",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "String"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "description",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "type",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "OBJECT",
                                    "name": "__Type"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "defaultValue",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "isDeprecated",
                            "type": {
                                "kind": "SCALAR",
                                "name": "Boolean"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "deprecationReason",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "OBJECT",
                    "name": "__Schema",
                    "description": "A GraphQL Introspection defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, the entry points for query, mutation, and subscription operations.",
                    "fields": [
                        {
                            "name": "description",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "types",
                            "description": "A list of all types supported by this server.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "LIST",
                                    "ofType": {
                                        "kind": "NON_NULL",
                                        "ofType": {
                                            "kind": "OBJECT",
                                            "name": "__Type"
                                        }
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "queryType",
                            "description": "The type that query operations will be rooted at.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "OBJECT",
                                    "name": "__Type"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "mutationType",
                            "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
                            "type": {
                                "kind": "OBJECT",
                                "name": "__Type"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "directives",
                            "description": "'A list of all directives supported by this server.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "LIST",
                                    "ofType": {
                                        "kind": "NON_NULL",
                                        "ofType": {
                                            "kind": "OBJECT",
                                            "name": "__Directive"
                                        }
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "subscriptionType",
                            "description": "'If this server support subscription, the type that subscription operations will be rooted at.",
                            "type": {
                                "kind": "OBJECT",
                                "name": "__Type"
                            },
                            "isDeprecated": false
                        }
                    ]
                },
                {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "fields": [
                        {
                            "name": "kind",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "ENUM",
                                    "name": "__TypeKind"
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "name",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "description",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "fields",
                            "args": [
                                {
                                    "name": "includeDeprecated",
                                    "type": {
                                        "kind": "SCALAR",
                                        "name": "Boolean"
                                    },
                                    "defaultValue": "false"
                                }
                            ],
                            "type": {
                                "kind": "LIST",
                                "ofType": {
                                    "kind": "NON_NULL",
                                    "ofType": {
                                        "kind": "OBJECT",
                                        "name": "__Field"
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "interfaces",
                            "type": {
                                "kind": "LIST",
                                "ofType": {
                                    "kind": "NON_NULL",
                                    "ofType": {
                                        "kind": "OBJECT",
                                        "name": "__Type"
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "possibleTypes",
                            "type": {
                                "kind": "LIST",
                                "ofType": {
                                    "kind": "NON_NULL",
                                    "ofType": {
                                        "kind": "OBJECT",
                                        "name": "__Type"
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "enumValues",
                            "args": [
                                {
                                    "name": "includeDeprecated",
                                    "type": {
                                        "kind": "SCALAR",
                                        "name": "Boolean"
                                    },
                                    "defaultValue": "false"
                                }
                            ],
                            "type": {
                                "kind": "LIST",
                                "ofType": {
                                    "kind": "NON_NULL",
                                    "ofType": {
                                        "kind": "OBJECT",
                                        "name": "__EnumValue"
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "inputFields",
                            "args": [
                                {
                                    "name": "includeDeprecated",
                                    "type": {
                                        "kind": "SCALAR",
                                        "name": "Boolean"
                                    },
                                    "defaultValue": "false"
                                }
                            ],
                            "type": {
                                "kind": "LIST",
                                "ofType": {
                                    "kind": "NON_NULL",
                                    "ofType": {
                                        "kind": "OBJECT",
                                        "name": "__InputValue"
                                    }
                                }
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "ofType",
                            "type": {
                                "kind": "OBJECT",
                                "name": "__Type"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "specifiedByURL",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": false
                        },
                        {
                            "name": "specifiedByUrl",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "isDeprecated": true,
                            "deprecationReason": "This legacy name has been replaced by `specifiedByURL`"
                        }
                    ]
                },
                {
                    "kind": "ENUM",
                    "name": "__TypeKind",
                    "description": "An enum describing what kind of type a given __Type is",
                    "enumValues": [
                        {
                            "name": "SCALAR",
                            "description": "Indicates this type is a scalar. 'specifiedByURL' is a valid field",
                            "isDeprecated": false
                        },
                        {
                            "name": "OBJECT",
                            "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
                            "isDeprecated": false
                        },
                        {
                            "name": "INTERFACE",
                            "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
                            "isDeprecated": false
                        },
                        {
                            "name": "UNION",
                            "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
                            "isDeprecated": false
                        },
                        {
                            "name": "ENUM",
                            "description": "Indicates this type is an enum. `enumValues` is a valid field.",
                            "isDeprecated": false
                        },
                        {
                            "name": "INPUT_OBJECT",
                            "description": "Indicates this type is an input object. `inputFields` is a valid field.",
                            "isDeprecated": false
                        },
                        {
                            "name": "LIST",
                            "description": "Indicates this type is a list. `ofType` is a valid field.",
                            "isDeprecated": false
                        },
                        {
                            "name": "NON_NULL",
                            "description": "Indicates this type is a non-null. `ofType` is a valid field.",
                            "isDeprecated": false
                        }
                    ]
                }
            ],
            "directives": [
                {
                    "name": "include",
                    "description": "Directs the executor to include this field or fragment only when the `if` argument is true",
                    "locations": [
                        "FIELD",
                        "FRAGMENT_SPREAD",
                        "INLINE_FRAGMENT"
                    ],
                    "args": [
                        {
                            "name": "if",
                            "description": "Included when true.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "Boolean"
                                }
                            }
                        }
                    ]
                },
                {
                    "name": "skip",
                    "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
                    "locations": [
                        "FIELD",
                        "FRAGMENT_SPREAD",
                        "INLINE_FRAGMENT"
                    ],
                    "args": [
                        {
                            "name": "if",
                            "description": "Skipped when true.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "Boolean"
                                }
                            }
                        }
                    ]
                },
                {
                    "name": "deprecated",
                    "description": "Marks the field, argument, input field or enum value as deprecated",
                    "locations": [
                        "FIELD_DEFINITION",
                        "ARGUMENT_DEFINITION",
                        "ENUM_VALUE",
                        "INPUT_FIELD_DEFINITION"
                    ],
                    "args": [
                        {
                            "name": "reason",
                            "description": "The reason for the deprecation",
                            "type": {
                                "kind": "SCALAR",
                                "name": "String"
                            },
                            "defaultValue": "\"No longer supported\""
                        }
                    ]
                },
                {
                    "name": "specifiedBy",
                    "description": "Exposes a URL that specifies the behaviour of this scalar.",
                    "locations": [
                        "SCALAR"
                    ],
                    "args": [
                        {
                            "name": "url",
                            "description": "The URL that specifies the behaviour of this scalar.",
                            "type": {
                                "kind": "NON_NULL",
                                "ofType": {
                                    "kind": "SCALAR",
                                    "name": "String"
                                }
                            }
                        }
                    ]
                }
            ]
        }
    }
}

Schema:

type Query {
    getAll: String
}

Expected Behavior

Schema explorer should work

Steps To Reproduce

No response

Environment

Anything else?

No response

acao commented 12 months ago

we call getIntrospectionQuery() from graphql-js, which is what is throwing the error.

you can see the introspection query for interfaces in the outbound request.

does the server you are using have an issue with introspecting interfaces, or require interfaces? you probably need to open a ticket with the maintainers of the spring boot implementation, as perhaps they are behind on the spec implementation

acao commented 8 months ago

@martinformi reopening here if indeed this is a bug on our end! (i think it is)