simonw / datasette-graphql

Datasette plugin providing an automatic GraphQL API for your SQLite databases
https://datasette-graphql-demo.datasette.io/
Apache License 2.0
98 stars 6 forks source link

GraphQLLocatedError: 'rows' #78

Open curiousleo opened 2 years ago

curiousleo commented 2 years ago

Error message

When I try to perform any query with the integrated GraphiQL editor, I get:

INFO:     172.17.0.1:43602 - "POST /graphql/OpenStreetMap HTTP/1.1" 500 Internal Server Error
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/promise/promise.py", line 844, in handle_future_result
    resolve(future.result())
  File "/usr/local/lib/python3.9/site-packages/datasette_graphql/utils.py", line 585, in resolve_table
    data["rows"] = [dict(zip(data["columns"], row)) for row in data["rows"]]
graphql.error.located_error.GraphQLLocatedError: 'rows'

Query result

The query result view (on the right hand side in GraphiQL) says:

{
  "data": {
    "buildings": null
  },
  "errors": [
    {
      "message": "'rows'",
      "locations": [
        {
          "line": 31,
          "column": 3
        }
      ],
      "path": [
        "buildings"
      ]
    }
  ]
}

Screenshot

image

Versions

$ pip list | grep -E 'datasette(-graphql)?\s'
datasette                 0.58.1
datasette-graphql         1.5
simonw commented 2 years ago

Could you try this again but run Datasette with datasette mydb.db --pdb and see if you can get a better stack trace? Or if you can share a copy of the database (or a cut-down copy that still illustrates the bug) I'd be happy to dig in and take a look.

simonw commented 2 years ago

It's also possible this is fixed by version 2.0, which I released today.

curiousleo commented 2 years ago

Here is the stack trace I'm getting.

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/graphql/type/definition.py", line 735, in fields
    fields = resolve_thunk(self._fields)
  File "/usr/local/lib/python3.9/site-packages/graphql/type/definition.py", line 264, in resolve_thunk
    return thunk() if callable(thunk) else thunk
  File "/usr/local/lib/python3.9/site-packages/graphene/types/schema.py", line 296, in create_fields_for_type
    field_type = create_graphql_type(field.type)
  File "/usr/local/lib/python3.9/site-packages/graphene/types/field.py", line 116, in type
    return get_type(self._type)
  File "/usr/local/lib/python3.9/site-packages/graphene/types/utils.py", line 42, in get_type
    return _type()
  File "/usr/local/lib/python3.9/site-packages/datasette_graphql/utils.py", line 626, in getter
    return table_classes[table]
KeyError: 'author'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/datasette/app.py", line 1254, in route_path
    response = await view(request, send)
  File "/usr/local/lib/python3.9/site-packages/datasette/app.py", line 1442, in async_view_fn
    response = await async_call_with_supported_arguments(
  File "/usr/local/lib/python3.9/site-packages/datasette/utils/__init__.py", line 977, in async_call_with_supported_arguments
    return await fn(*call_with)
  File "/usr/local/lib/python3.9/site-packages/datasette_graphql/__init__.py", line 81, in view_graphql
    schema = (await schema_for_database_via_cache(datasette, database=database)).schema
  File "/usr/local/lib/python3.9/site-packages/datasette_graphql/utils.py", line 79, in schema_for_database_via_cache
    schema = await schema_for_database(datasette, database)
  File "/usr/local/lib/python3.9/site-packages/datasette_graphql/utils.py", line 235, in schema_for_database
    schema=graphene.Schema(
  File "/usr/local/lib/python3.9/site-packages/graphene/types/schema.py", line 430, in __init__
    self.graphql_schema = GraphQLSchema(
  File "/usr/local/lib/python3.9/site-packages/graphql/type/schema.py", line 208, in __init__
    collect_referenced_types(query)
  File "/usr/local/lib/python3.9/site-packages/graphql/type/schema.py", line 423, in collect_referenced_types
    collect_referenced_types(field.type)
  File "/usr/local/lib/python3.9/site-packages/graphql/type/schema.py", line 423, in collect_referenced_types
    collect_referenced_types(field.type)
  File "/usr/local/lib/python3.9/site-packages/graphql/type/schema.py", line 422, in collect_referenced_types
    for field in named_type.fields.values():
  File "/usr/local/lib/python3.9/functools.py", line 993, in __get__
    val = self.func(instance)
  File "/usr/local/lib/python3.9/site-packages/graphql/type/definition.py", line 737, in fields
    raise TypeError(f"{self.name} fields cannot be resolved. {error}")
TypeError: book fields cannot be resolved. 'author'

The only way for me to reproduce this is when there is a column declaration which references a column in a table that is marked as hidden: true in the Datasette metadata.

books.sql metadata.yaml

Reproduction steps:

sqlite3 books.db <books.sql
datasette . # Assuming the GraphQL plugin is installed and metadata.yaml is saved to the current directory

Verified with:

$ pip list | grep 'datasette'
datasette           0.61.1
datasette-graphql   2.0.1
simonw commented 1 year ago

I think I've managed to replicate this bug here:

https://fivethirtyeight.datasettes.com/graphql?query={%0A%20%20love_actually_love_actually_adjacencies%20{%0A%20%20%20%20nodes%20{%0A%20%20%20%20%09bill_nighy%0A%20%20%20%20%20%20%0A%20%20%20%20}%0A%20%20}%0A}

Query:

{
  love_actually_love_actually_adjacencies {
    nodes {
        bill_nighy
    }
  }
}

Response:

{
  "data": {
    "love_actually_love_actually_adjacencies": null
  },
  "errors": [
    {
      "message": "'rows'",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "love_actually_love_actually_adjacencies"
      ]
    }
  ]
}