Skip to content

Commit 5a0d960

Browse files
committed
Add IntoFieldError to error docs
Part of graphql-rust#8.
1 parent da3d21b commit 5a0d960

File tree

1 file changed

+123
-1
lines changed

1 file changed

+123
-1
lines changed

docs/types/objects/error_handling.md

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use juniper::FieldResult;
1717
use std::path::PathBuf;
1818
use std::fs::File;
1919
use std::io::Read;
20+
use std::str;
2021

2122
struct Example {
2223
filename: PathBuf,
@@ -29,6 +30,15 @@ graphql_object!(Example: () |&self| {
2930
file.read_to_string(&mut contents)?;
3031
Ok(contents)
3132
}
33+
field foo() -> FieldResult<Option<String>> {
34+
// Some invalid bytes.
35+
let invalid = vec![128, 223];
36+
37+
match str::from_utf8(&invalid) {
38+
Ok(s) => Ok(Some(s.to_string())),
39+
Err(e) => Err(e)?,
40+
}
41+
}
3242
});
3343

3444
# fn main() {}
@@ -41,6 +51,118 @@ there - those errors are automatically converted into `FieldError`.
4151

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

0 commit comments

Comments
 (0)