Skip to content
This repository has been archived by the owner on Sep 2, 2022. It is now read-only.

Error sources #2199

Closed
timsuchanek opened this issue Apr 8, 2018 · 4 comments
Closed

Error sources #2199

timsuchanek opened this issue Apr 8, 2018 · 4 comments

Comments

@timsuchanek
Copy link
Contributor

Motivating the Problem

Let's say you're writing an application with the common Yoga/Binding/Prisma stack:

+-----+   +------------+   +---------------+   +------+
| App |---|GraphQL Yoga|---|GraphQL Binding|---|Prisma|
+-----+   +------------+   +---------------+   +------+

This has many benefits as better flexibility and less code, but makes locating GraphQL Errors right now pretty hard. That's the case, because in this stack we have 3 GraphQL Schemas that are involved to process a query.

  1. GraphQL Yoga: Yoga exposes the application schema, an instance of GraphQLSchema from graphql js.
  2. GraphQL Binding: In order to provide the nice args experience for bindings, another schema is needed here - under the hood a "remote executable schema" is used.
  3. Prisma: Prisma, using Sangria, also provides a GraphQL Schema.

Where did the error happen?

Let's say we get a response like this: (taken from prisma-labs/graphql-prisma-typescript#92)

{
  "data": null,
  "errors": [
    {
      "message": "Field 'places' of type 'Place' must have a sub selection. (line 2, column 3):\n  places(where: $_where, orderBy: $_orderBy, skip: $_skip, after: $_after, before: $_before, first: $_first, last: $_last)\n  ^",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "homesInPriceRange"
      ]
    }
  ]
}

We now know that a subselection is missing. We suspect this error to occur in either the Yoga schema or the binding schema. But where did it actually happen? We don't know.

This is a simple example, where only one source is used in Yoga. There could be hundreds of microservices used by Yoga, where the overview would be totally lost. We need a solution for this.

Proposal

In order to know where an error comes from, we could add a property to it, that describes its source.

Right now the spec for the error type looks like this:

type Error {
  message: String!
  path: [String!]
  location: [Location!]
}

In Prisma we added 2 more properties, requestId and code:

type Error {
  message: String!
  path: [String!]
  location: [Location!]
  requestId: String!
  code: Int
}

The proposal is, too add a property called source: String. In our example from above, it would look like this:

{
  "data": null,
  "errors": [
    {
      "message": "Field 'places' of type 'Place' must have a sub selection. (line 2, column 3):\n  places(where: $_where, orderBy: $_orderBy, skip: $_skip, after: $_after, before: $_before, first: $_first, last: $_last)\n  ^",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "homesInPriceRange"
      ],
      "source": "yoga"
    }
  ]
}

Now we can see, that the error has been triggered in the yoga schema.

Moving forward

This is a rough proposal, how a solution for finding the error source could look like.
If you're interested in working on this, please let us know in a comment or join our public Graphcool Slack!

@peterschussheim
Copy link
Contributor

@timsuchanek i'd be happy to work on this. Feeling the pain right now trying to debug missing sub selection errors and something like your proposal would be very helpful.

@divyenduz
Copy link
Contributor

divyenduz commented Jun 26, 2018

Extending the original proposal, what we essentially want to do is to recursively preserve the errors from graphql spec for multiple schemas across a delegation path.

This can be achieved by adding delegrationErrors and schemaId key to error extensions.

  • delegationErrors will recursively capture all errors across the delegation path and preserve them in a similar structure to the errors field.

  • schemaId will be a string/url as a unique identifier for any schema on the delegation path.

An example response of graphql server implementing such a sources solution would look like this:

{
  "errors": [
    {
      "message": "Name for character with ID 1002 could not be fetched.",
      "locations": [{"line": 6, "column": 7}],
      "path": ["hero", "heroFriends", 1, "name"],

      "extensions": {
        "schemaId": "schema_1",
        "code": "CAN_NOT_FETCH_BY_ID",
        "timestamp": "Fri Feb 9 14:33:09 UTC 2018",
        "delegationErrors": [
          {
            "message": "Name for character with ID 1002 could not be fetched.",
            "locations": [{"line": 6, "column": 7}],
            "path": ["hero", "heroFriends", 1, "name"],
            "extensions": {
              "schemaId": "schema_2",
              "code": "CAN_NOT_FETCH_BY_ID",
              "timestamp": "Fri Feb 9 14:33:09 UTC 2018"
            }
          }
        ]
      }
    }
  ]
}

@jgoux
Copy link

jgoux commented Sep 10, 2018

I'm having a hard time dealing with my errors from Prisma as they aren't machine readable. Please fill the extensions key with useful infos (code, path, field...). 🙏

@stale
Copy link

stale bot commented Dec 6, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 10 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the status/stale Marked as state by the GitHub stalebot label Dec 6, 2018
@divyenduz divyenduz removed the status/stale Marked as state by the GitHub stalebot label Dec 6, 2018
@janpio janpio closed this as completed Sep 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants