File: backtrace_annotations.md

package info (click to toggle)
ruby-graphql 1.13.15-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 8,904 kB
  • sloc: ruby: 69,655; yacc: 444; javascript: 330; makefile: 6
file content (75 lines) | stat: -rw-r--r-- 3,454 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
---
title: Backtrace Annotations
layout: guide
doc_stub: false
search: true
section: Queries
desc: Use the GraphQL backtrace for debugging
index: 12
experimental: true
---

`context` objects have a `backtrace` which shows its GraphQL context. You can print the backtrace during query execution:

```ruby
puts context.backtrace
# Loc  | Field                         | Object       | Arguments             | Result
# 3:13 | User.login                    | #<User id=1> | {"message"=>"Boom"}   | #<RuntimeError: This is broken: Boom>
# 2:11 | Query.user                    | nil          | {"login"=>"rmosolgo"} | {}
# 1:9  | query                         | nil          | {"msg"=>"Boom"}       |
```

The backtrace contains some execution data:

- `Loc` is the `line:column` of the field in the query string
- `Field` is the `TypeName.fieldName` of the fields in the backtrace
- `Object` is the `obj` for query resolution (used for resolving the given field), equivalent to `obj.inspect`
- `Arguments` are the GraphQL arguments for field resolution (including any default values and variable values)
- `Result` is the GraphQL-ready result which is being constructed (it may be incomplete if the query is still in-progress)

## Wrapping Errors

You can wrap unhandled errors with a GraphQL error with `GraphQL::Backtrace`.

To enable this feature for a query, add `backtrace: true` to your `context`, for example:

```ruby
# Wrap this query with backtrace annotation
MySchema.execute(query_string, context: { backtrace: true })
```

Or, to _always_ wrap backtraces, add it to your schema definition with `use`, for example:

```ruby
class MySchema < GraphQL::Schema
  # Always wrap backtraces with GraphQL annotation
  use GraphQL::Backtrace
end
```

Now, any unhandled errors will be wrapped by `GraphQL::Backtrace::TracedError`, which prints out the GraphQL backtrace, too. For example:

```
Unhandled error during GraphQL execution:

  This is broken: Boom
    /Users/rmosolgo/code/graphql-ruby/spec/graphql/backtrace_spec.rb:27:in `block (3 levels) in <top (required)>'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/schema/build_from_definition/resolve_map.rb:57:in `call'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/schema/build_from_definition.rb:171:in `block in build_object_type'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/schema/build_from_definition.rb:280:in `block (2 levels) in build_fields'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/field.rb:228:in `resolve'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/execution/execute.rb:253:in `call'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/schema/middleware_chain.rb:45:in `invoke_core'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/schema/middleware_chain.rb:38:in `invoke'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/execution/execute.rb:107:in `resolve_field'
    /Users/rmosolgo/code/graphql-ruby/lib/graphql/execution/execute.rb:71:in `block (2 levels) in resolve_selection'
    ... and 65 more lines

Use #cause to access the original exception (including #cause.backtrace).

GraphQL Backtrace:
Loc  | Field                         | Object     | Arguments           | Result
3:13 | Thing.raiseField as boomError | :something | {"message"=>"Boom"} | #<RuntimeError: This is broken: Boom>
2:11 | Query.field1                  | "Root"     | {}                  | {}
1:9  | query                         | "Root"     | {"msg"=>"Boom"}     | {}
```