Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FunctionDataFetcher: does not handle Error descendant Throwables in runBlockingFunction in conjunction with GraphQL Java graphql/execution/ExecutionStrategy.java #1965

Open
wallind opened this issue Apr 22, 2024 · 0 comments · May be fixed by #1966
Labels
type: bug Something isn't working

Comments

@wallind
Copy link

wallind commented Apr 22, 2024

Library Version

Latest 7.1.1

Describe the bug

The way this library interacts with graphql-java, any non-blocking resolvers that lead to a result of a thrown Throwable descendant from Error and not Exception will not be handled as expected in the errors field of the response, but rather result in a HTTP - 500 error (depending on specific server implementation).

So like this example here:

```kotlin
class Product(val id: ID, val name: String) {
suspend fun reviews(): List<Reviews> {
// logic to fetch reviews here
}
}
```

If you instead had this (fun instead of suspend fun):

class Product(val id: ID, val name: String) {
  fun reviews(): List<Reviews> { ... }
}

You run into the problem where this will be handled as expected:

class Product(val id: ID, val name: String) {
  fun reviews(): List<Reviews> { throw Exception("it works as expected; this ends up in errors") }
}

but this will not:

class Product(val id: ID, val name: String) {
  fun reviews(): List<Reviews> { throw Error("it works as expected; this ends up in errors") }
}

This is because of the graphql-java parent scope that does catch any Exception but not Error descendant Throwables:

https://github.com/graphql-java/graphql-java/blob/25667a13e528a2b2c4fa372b363ffbb00184316a/src/main/java/graphql/execution/ExecutionStrategy.java#L322-L339.

In my case a nested scope throwing the kotlin.NotImplementedError brought this to my attention.

To Reproduce

No particular schema/config needed, just have the following:

@Component
class FooQuery: Query {
    fun getFoo(): Foo {
        return Foo("hello world",)
    }
}
data class Foo(val bar: String) {
    fun nonSuspendFunctionException(): String {
        throw Exception("This is an exception - and works fine")
    }

    fun nonSuspendFunctionError(): String {
        throw Error("This is an error - and DOESN'T work fine")
    }

    suspend fun suspendFunctionException(): String {
        throw Exception("This is an exception - and works fine")
    }

    suspend fun suspendFunctionError(): String {
        throw Error("This is an error - and works fine")
    }
}

Attached is a minimal Spring Boot app you can run locally and easily observe the behavior using following query and uncommenting the various resolvers:

query Reproduction {
  getFoo {
    # nonSuspendFunctionException
    # nonSuspendFunctionError
    # suspendFunctionException
    # suspendFunctionError
  }
}

graphql-kotlin-error-example.zip

Expected behavior

The expected errors handling like this:

image

Instead of the current behavior which is an unhandled server error like this:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
1 participant