farmerbb
08/04/2025, 11:14 PMfarmerbb
08/04/2025, 11:14 PMquery test {
exampleField(first: 15) {
edges {
node {
content {
id
}
}
}
}
}
On the schema, the content
field inside node
is marked as non-nullable:
type Node {
content: Content!
# ... other fields
}
When I run the query inside the IDE, I get back the following:
{
"data": {
"exampleField": {
"edges": [
{
"node": null
},
{
"node": {
"content": {
"id": "some-id-1"
}
}
},
{
"node": {
"content": {
"id": "some-id-2"
}
}
}
]
}
},
"errors": [
{
"message": "Cannot return null for non-nullable field",
"path": [
"exampleField",
"edges",
0,
"node",
"content"
]
}
],
"extensions": {
"valueCompletion": [
{
"message": "Cannot return null for non-nullable field Node.content",
"path": [
"exampleField",
"edges",
0,
"node",
"content"
]
}
]
}
}
which obviously means that the server is breaking the contract defined by the schema and returning null data, where it should be non-null.
I would expect to still see Apollo Kotlin return the partial data and the errors, under response.data
and response.errors
respectively, but they are both null. Instead, under response.exception
I get back an ApolloNetworkException: Error while reading JSON response
with the underlying platformCause
being `IllegalStateException: Failed to buffer json reader, expected BEGIN_OBJECT
but found NULL
json token`.
Here's an example of some code that I have for handling Apollo responses:
when {
response.hasErrors() -> {
LogEntry(
apolloOperation = response.operation.toString(),
message = errorMsg(response),
).also(log::e)
// Continue to send up a response, to account for partial data
Resource.Response(transform(response))
}
exception != null -> logAndReturnFailure(response, exception)
else -> Resource.Response(transform(response))
}
My expectation is that Apollo would be able to handle the unexpected null, and still return the partial data in the errors, hitting the first case above. Instead, it's hitting the second case, since there are no errors or partial data, but an exception instead.
Are there any configuration options, etc. that I can enable to work around this issue and get back the data and errors? Or is there some extra handling that can be added to Apollo Kotlin for cases like this where the server is violating schema nullability?mbonnin
08/05/2025, 6:25 AMEdge.node
above?farmerbb
08/05/2025, 3:02 PMtype Edge {
node: Node!
cursor: String!
}
mbonnin
08/05/2025, 3:03 PMmbonnin
08/05/2025, 3:04 PMmbonnin
08/05/2025, 3:05 PMfarmerbb
08/05/2025, 3:07 PMmbonnin
08/05/2025, 3:09 PMmbonnin
08/05/2025, 3:09 PMfarmerbb
08/05/2025, 3:11 PMmbonnin
08/05/2025, 3:55 PM@catch
:
extend schema @link(
url: "<https://specs.apollo.dev/nullability/v0.4>",
import: ["@catch", "CatchTo", "@catchByDefault"]
)
extend schema @catchByDefault(to: NULL)
type Query {
foo: Foo!
}
type Foo {
bar: Int!
}
query:
query GetFoo {
foo @catch(to: NULL) {
# ^ This is the IMPORTANT part
bar
}
}
mbonnin
08/05/2025, 3:55 PM// language=JSON
val json = """
{
"foo": null
}
""".trimIndent()
val data = Buffer().writeUtf8(json).jsonReader()
.let {
GetFooQuery().parseData(it)
}
assertEquals(null, data!!.foo)
mbonnin
08/05/2025, 3:55 PM@catch
will recover from it