20

I’m building out a simple HotChocolate GraphQl server and HotChocolate throws an Unexpected Execution Error, but doesn't expose any information about the error, as soon as I post a request against it. It doesn't matter how I post the request against the backend (BananaCakePop, Postman, Insomnia, ...).
The reponse looks like this:

{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "pong"
      ]
    }
  ],
  "data": {
    "pong": null
  }
}

The request response contains no further information and nothing is logged to the applications console. What would be a reasonable next step to try and figure out what went wrong?

FredericBirke
  • 1,002
  • 1
  • 7
  • 13

2 Answers2

24

Per default HotChocolate does not expose the details of your exceptions, if no debugger is attached. So to get your error message you could either:

  • Attach a debugger to your server, which in turn will then expose the exceptions details in the request (a.k.a. start your server in debug :D)
  • Change this behavior in a way that better suits your development style.

This is how you can change the default behavior in V11 or V12:

public class Startup
{
    private readonly IWebHostEnvironment _env;

    public Startup(IWebHostEnvironment env)
    {
        _env = env;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddGraphQLServer()
            ...
            // You can change _env.IsDevelopment() to whatever condition you want.
            // If the condition evaluates to true, the server will expose it's exceptions details
            // within the reponse.
            .ModifyRequestOptions(opt => opt.IncludeExceptionDetails = _env.IsDevelopment());  
    }
}

This is how you can change the default behavior in V10:

public class Startup
{
    private readonly IWebHostEnvironment _env;

    public Startup(IWebHostEnvironment env)
    {
        _env = env;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGraphQL(
            Schema.Create(builder =>
            {
                ...
            }),
            // You can change _env.IsDevelopment() to whatever condition you want.
            // If the condition evaluates to true, the server will expose it's exceptions details
            // within the reponse.
            new QueryExecutionOptions {IncludeExceptionDetails = _env.IsDevelopment()}
        );
    }
}

You can also add an IErrorFilter to you application, that could, for example, log your exceptions to your locale console, or transform Exceptions to GraphQlErrors. For more information about this topic check:

FredericBirke
  • 1,002
  • 1
  • 7
  • 13
5

I'm in the same boat, also needing exception details

and nothing is logged to the applications console

I suggest this is where we should add error logging, as opposed to the response returned to the GraphQL client.

Setting up proper logging will help us in Production as well as Development envs, if we run into an issue there.

We'll need to hook into Hot Chocolate's Diagnostics. There are several types of diagnostic events, I'm just going to set up one for execution events, as that's where the error is in my case. I was only able to test ResolverError, but the rest should work.

    public class ErrorLoggingDiagnosticsEventListener : ExecutionDiagnosticEventListener
    {
        private readonly ILogger<ErrorLoggingDiagnosticsEventListener> log;

        public ErrorLoggingDiagnosticsEventListener(
            ILogger<ErrorLoggingDiagnosticsEventListener> log)
        {
            this.log = log;
        }

        public override void ResolverError(
            IMiddlewareContext context,
            IError error)
        {
            log.LogError(error.Exception, error.Message);
        }

        public override void TaskError(
            IExecutionTask task,
            IError error)
        {
            log.LogError(error.Exception, error.Message);
        }

        public override void RequestError(
            IRequestContext context,
            Exception exception)
        {
            log.LogError(exception, "RequestError");
        }

        public override void SubscriptionEventError(
            SubscriptionEventContext context,
            Exception exception)
        {
            log.LogError(exception, "SubscriptionEventError");
        }

        public override void SubscriptionTransportError(
            ISubscription subscription,
            Exception exception)
        {
            log.LogError(exception, "SubscriptionTransportError");
        }
    }

Now wire that up in startup config.

    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddGraphQLServer()
            .AddDiagnosticEventListener<ErrorLoggingDiagnosticsEventListener>()
            ...
            ;
    }

Exceptions are now logged to your configured sink for ILogger.

Trey Mack
  • 4,215
  • 2
  • 25
  • 31