Skip to content

Commit 0f5ba66

Browse files
committed
Add IntoFieldError to error docs
Part of graphql-rust#8.
1 parent e280563 commit 0f5ba66

File tree

1 file changed

+121
-1
lines changed

1 file changed

+121
-1
lines changed

docs/types/objects/error_handling.md

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ graphql_object!(Example: () |&self| {
2929
file.read_to_string(&mut contents)?;
3030
Ok(contents)
3131
}
32+
field foo() -> FieldResult<Option<&str>> {
33+
// Some invalid bytes.
34+
let invalid = vec![128, 223];
35+
36+
match str::from_utf8(invalid) {
37+
Ok(s) => Ok(Some(s)),
38+
Err(e) => Err(e),
39+
}
40+
}
3241
});
3342

3443
# fn main() {}
@@ -41,6 +50,117 @@ there - those errors are automatically converted into `FieldError`.
4150

4251
When a field returns an error, the field's result is replaced by `null`, an
4352
additional `errors` object is created at the top level of the response, and the
44-
execution is resumed. If an error is returned from a non-null field, such as the
53+
execution is resumed. For example, with the previous example and the following
54+
query:
55+
56+
```graphql
57+
{
58+
example {
59+
contents
60+
foo
61+
}
62+
}
63+
```
64+
65+
If `str::from_utf8` resulted in a `std::str::Utf8Error`, the following would be
66+
returned:
67+
68+
!FILENAME Response for nullable field with error
69+
70+
```js
71+
{
72+
"data": {
73+
"example": {
74+
contents: "<Contents of the file>",
75+
foo: null,
76+
}
77+
},
78+
"errors": [
79+
"message": "invalid utf-8 sequence of 2 bytes from index 0",
80+
"locations": [{ "line": 2, "column": 4 }])
81+
]
82+
}
83+
```
84+
85+
If an error is returned from a non-null field, such as the
4586
example above, the `null` value is propagated up to the first nullable parent
4687
field, or the root `data` object if there are no nullable fields.
88+
89+
For example, with the following query:
90+
91+
```graphql
92+
{
93+
example {
94+
contents
95+
}
96+
}
97+
```
98+
99+
If `File::open()` above resulted in `std::io::ErrorKind::PermissionDenied`, the
100+
following would be returned:
101+
102+
!FILENAME Response for non-null field with error and no nullable parent
103+
104+
```js
105+
{
106+
"errors": [
107+
"message": "Permission denied (os error 13)",
108+
"locations": [{ "line": 2, "column": 4 }])
109+
]
110+
}
111+
```
112+
113+
## Structured errors
114+
115+
Sometimes it may be desirable to include structured error information to
116+
clients. This can be accomplished by implementing [`IntoFieldError`](https://docs.rs/juniper/latest/juniper/trait.IntoFieldError.html), as the following example illustrates:
117+
118+
```rust
119+
# #[macro_use] extern crate juniper;
120+
use juniper::{FieldError, IntoFieldError};
121+
122+
enum CustomError {
123+
WhateverNotSet,
124+
}
125+
126+
impl IntoFieldError for CustomError {
127+
fn into_field_error(self) -> FieldError {
128+
match self {
129+
CustomError::WhateverNotSet => FieldError::new(
130+
"Whatever does not exist",
131+
graphql_value!({
132+
"type": "NO_WHATEVER"
133+
}),
134+
),
135+
}
136+
}
137+
}
138+
139+
struct Example {
140+
whatever: Option<bool>,
141+
}
142+
143+
graphql_object!(Example: () |&self| {
144+
field whatever() -> Result<bool, CustomError> {
145+
if let Some(value) = self.whatever {
146+
return value;
147+
}
148+
Err(CustomError::WhateverNotSet)
149+
});
150+
151+
# fn main() {}
152+
```
153+
154+
The structured error information is included in the [`extensions`](https://facebook.github.io/graphql/June2018/#sec-Errors) key:
155+
156+
```js
157+
{
158+
"errors": [
159+
"message": "Whatever does not exist",
160+
"locations": [{ "line": 2, "column": 4 }]),
161+
"extensions": {
162+
"type": "NO_WHATEVER"
163+
}
164+
]
165+
}
166+
```

0 commit comments

Comments
 (0)