Validation error using '@include' directive if schema comes from introspection
SuperBo opened this issue · 10 comments
When I try to use "@include" directive in my string query, I got this error:
graphql.error.graphql_error.GraphQLError: Unknown directive '@include'.
I think "@include" and "@Skip" are in standards of GraphQL https://graphql.org/learn/queries/#directives
Version in my environment
gql[requests]==3.0.0b1
graphql-core==3.1.6; python_version >= '3.6' and python_version < '4'
GraphQL Query
query fetchPool($with_swap: Boolean!) {
pool(id: "0x83abecf7204d5afc1bea5df734f085f2535a9976") {
id
createdAtTimestamp
swaps (first: 2) @include(if: $with_swap ) {
id
timestamp
}
}
}
Full stack trace:
Traceback (most recent call last):
File "test.py", line 27, in
result = client.execute(q, variable_values= {'with_swap': True})
File "/Users/ynguyen/.local/share/virtualenvs/activelp_v1_prod-cEysbnrO/lib/python3.8/site-packages/gql/client.py", line 186, in execute
return self.execute_sync(document, *args, **kwargs)
File "/Users/ynguyen/.local/share/virtualenvs/activelp_v1_prod-cEysbnrO/lib/python3.8/site-packages/gql/client.py", line 134, in execute_sync
return session.execute(document, *args, **kwargs)
File "/Users/ynguyen/.local/share/virtualenvs/activelp_v1_prod-cEysbnrO/lib/python3.8/site-packages/gql/client.py", line 389, in execute
result = self._execute(
File "/Users/ynguyen/.local/share/virtualenvs/activelp_v1_prod-cEysbnrO/lib/python3.8/site-packages/gql/client.py", line 328, in _execute
self.client.validate(document)
File "/Users/ynguyen/.local/share/virtualenvs/activelp_v1_prod-cEysbnrO/lib/python3.8/site-packages/gql/client.py", line 129, in validate
raise validation_errors[0]
graphql.error.graphql_error.GraphQLError: Unknown directive '@include'.GraphQL request:6:22
5 | createdAtTimestamp
6 | swaps (first: 2) @include(if: $with_swap ) {
| ^
7 | id
Hi,
Which versions of gql and graphql-core are you using ?
Could you please post your query and the full stack trace ?
Hi @leszekhanusz , I've just updated my OP.
How did you provide your schema? By using introspection or by providing your own schema.graphql file?
Does the schema include the @include
directive? (I don't know if it is needed)
I set "fetch_schema_from_transport" in client to True. I found out that when I switch "fetch_schema_from_transport" to False, the query can work now.
This my full test code if you interest
import gql
from gql.transport.requests import RequestsHTTPTransport
query = """
query fetchPool($with_swap: Boolean!) {
pool(id: "0x83abecf7204d5afc1bea5df734f085f2535a9976") {
id
createdAtTimestamp
swaps (first: 2) @include(if: $with_swap ) {
id
timestamp
}
}
}
"""
UNISWAP_V3_ENDPOINT = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'
transport = RequestsHTTPTransport(
url=UNISWAP_V3_ENDPOINT, verify=True, retries=3,
)
client = gql.Client(transport=transport, fetch_schema_from_transport=True)
q = gql.gql(query)
result = client.execute(q, variable_values= {'with_swap': True})
print(result)
I tried to valide your query using a provided schema.graphql
file but I had the following error:
graphql.error.graphql_error.GraphQLError: Field 'pool' argument 'subgraphError' of type '_SubgraphErrorPolicy_!' is required, but it was not provided.
GraphQL request:3:3
2 | query fetchPool($with_swap: Boolean!) {
3 | pool(id: "0x83abecf7204d5afc1bea5df734f085f2535a9976") {
| ^
4 | id
This was solved by adding the required subgraphError field:
import gql
from gql.transport.requests import RequestsHTTPTransport
query = """
query fetchPool($with_swap: Boolean!) {
pool(id: "0x83abecf7204d5afc1bea5df734f085f2535a9976", subgraphError: allow) {
id
createdAtTimestamp
swaps (first: 2) @include(if: $with_swap ) {
id
timestamp
}
}
}
"""
UNISWAP_V3_ENDPOINT = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'
with open("./schema.graphql") as f:
schema_str = f.read()
transport = RequestsHTTPTransport(
url=UNISWAP_V3_ENDPOINT, verify=True, retries=3,
)
client = gql.Client(transport=transport, schema=schema_str)
q = gql.gql(query)
result = client.execute(q, variable_values= {'with_swap': True})
print(result)
This is probably a bug in graphql-core. It is not normal that the include directive is not supported if the schema is fetched from the backend using introspection.
Thanks for your report!
@Cito could you please take a look at this bug?
@leszekhanusz I don't see where the problem is. I can run your example without error.
@Cito I have received your message in a notification email but it does not appear here. GitHub having some issues perhaps?
Anyway to answer your question:
Yes, that's the point, it works if the schema is built from a file but not if the schema is built from introspection.
Ultimately, the problem lies in differences between the build_ast_schema
and build_client_schema
of graphql-core.
In build_ast_schema
, there is this code to add the specified directives:
# If specified directives were not explicitly declared, add them.
if not any(directive.name == "skip" for directive in directives):
directives.append(GraphQLSkipDirective)
if not any(directive.name == "include" for directive in directives):
directives.append(GraphQLIncludeDirective)
if not any(directive.name == "deprecated" for directive in directives):
directives.append(GraphQLDeprecatedDirective)
if not any(directive.name == "specifiedBy" for directive in directives):
directives.append(GraphQLSpecifiedByDirective)
There is nothing corresponding in the build_client_schema
function.
Hi @leszekhanusz - yes, I understood the problem after reading again and therefore deleted my comment.
As you already noticed, the problem is the different behavior of build_client_schema
and build_ast_schema
which is inherited from GraphQL.js. The default directives like include
are not added automatically with build_client_schema
. As a workaround, you could do something like this to "normalize" the schema after creating it from introspection:
self.client.schema = build_ast_schema(parse(print_schema(self.client.schema)))
Or, you could somehow fumble the missing default directives into introspection['__schema']['directives']
before calling build_client_schema
.
All of this is ugly, that's why I opened that ticket with GraphQL.js now. If it is fixed there, I will port it to GraphQL-core then.
Fixed in version 3.0.0rc0