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

log unexpected errors in the server console by default #1584

Closed
Tracked by #1358
qsona opened this issue Aug 12, 2022 · 4 comments · Fixed by #2084
Closed
Tracked by #1358

log unexpected errors in the server console by default #1584

qsona opened this issue Aug 12, 2022 · 4 comments · Fixed by #2084
Assignees
Milestone

Comments

@qsona
Copy link

qsona commented Aug 12, 2022

Describe the bug

When an error thrown from context function, no error logs are shown in standard output/error.

Implementation:

createServer({
  // ... ,
  context: () => { throw new Error('foo') },
  // ..., 
})

Then I open the GraphiQL page, the response is

{
  "data": null,
  "errors": [
    {
      "message": "Unexpected error."
    }
  ]
}

but no error logs are shown up, so it's hard to find the cause.

I tried useLogger() and useErrorHandler() plugins but both didn't catch that error.

Your Example Website or App

https://codesandbox.io/s/summer-brook-tvigl0?file=/src/main.ts

Steps to Reproduce the Bug or Issue

  1. Create a minimal app with graphql-yoga, and set context value as a function that throws an error
  2. Open http://localhost:4000/graphql in your browser, or just send a introspection query

Expected behavior

As a developer, I expected the error messages are shown.

Screenshots or Videos

No response

Platform

  • OS: macOS
  • NodeJS: 16.10.0
  • @graphql-yoga/* version(s): 2.5.0, 2.13.6

Additional context

Sorry, I haven't investigate whether this problem is related graphql-yoga or envelop.

@n1ru4l
Copy link
Collaborator

n1ru4l commented Aug 12, 2022

Hey @qsona, thank you for using GraphQL Yoga!

Currently, errors are not logged to the console.

The original error SHOULD be included within the errors extension.originalError field within the execution result sent from the server, when you set the maskedErrors.isDev to true (or automatically when process.env.NODE_ENV is set to 'development' (See the error masking documentation).

HOWEVER, there is currently a bug within envelop that causes the error message to be swallowed. I am working on a fix of that here:

Let's track this here instead and keep this issue as a general logging issue: #1585


For now, you can use the following workaround, by specifying your own logger plugin: https://codesandbox.io/s/yoga-log-unexpected-errors-to-the-console-vhir52


We are currently working on GraphQL Yoga v3 (see our roadmap #1358). We want to make sure that Yoga v3 has the best developer experience. Logging unexpected errors to the console seems like something we should probably do.

In which kind of format would you expect these logs?

@n1ru4l n1ru4l removed the stage/2-failing-test A failing test was created that describes the issue label Aug 12, 2022
@n1ru4l n1ru4l added this to the v3 milestone Aug 12, 2022
@n1ru4l n1ru4l changed the title No error logs are shown up when creating context failed log unexpected errors in the server console by default Aug 12, 2022
@qsona
Copy link
Author

qsona commented Aug 13, 2022

@n1ru4l Sorry my report was a bit inaccurate.
On my original app, I'm specifying NODE_ENV=development and using the useErrorHandler plugin. The error thrown by context function isn't handled by both, so I created this issue.

The workaround you showed ( onPluginInit(ctx) { ctx.registerContextErrorHandler // ... ) perfectly worked on my app. Thank you very much!

In which kind of format would you expect these logs?

I don't have a strong opinion about log format, but I'm basically satisfied with current way, I mean maskedErrors option and
useErrorHandler plugin. I'm thinking that the error thrown by creating context can be regarded as expected, so it just seems better if useErrorHandler catches it. (It's just an innocent opinion, of course I know it's not easy)

@lenolib
Copy link

lenolib commented Sep 1, 2022

I have a similar problem, where e.g. errors thrown in any callback supplied to plugins loses their stack traces and can be very tedious to track down.
This is the line that seems responsible for losing the error stack https://github.com/dotansimha/graphql-yoga/blob/master/packages/common/src/GraphQLYogaError.ts#L36
A typical unhelpful error that gets returned could be:

{
  data: null,
  errors: [
    {
      message: "Cannot read properties of undefined (reading 'somewhere_in_my_code')"
    }
  ]
}

It would be great if such errors somehow could be logged, maybe using the debug library.

@TorbjornHoltmon
Copy link

TorbjornHoltmon commented Oct 30, 2022

Hey @qsona, thank you for using GraphQL Yoga!

Currently, errors are not logged to the console.

The original error SHOULD be included within the errors extension.originalError field within the execution result sent from the server, when you set the maskedErrors.isDev to true (or automatically when process.env.NODE_ENV is set to 'development' (See the error masking documentation).

HOWEVER, there is currently a bug within envelop that causes the error message to be swallowed. I am working on a fix of that here:

Let's track this here instead and keep this issue as a general logging issue: #1585

For now, you can use the following workaround, by specifying your own logger plugin: https://codesandbox.io/s/yoga-log-unexpected-errors-to-the-console-vhir52

We are currently working on GraphQL Yoga v3 (see our roadmap #1358). We want to make sure that Yoga v3 has the best developer experience. Logging unexpected errors to the console seems like something we should probably do.

In which kind of format would you expect these logs?

I am currently having issues writing error handling with yoga v3.
In v2, I could just got the original error from the result, and handle it as I pleased.

In v3 the errors that I throw seems lost.

I have been trying to figgure out when the my error is converted to a GraphQLErorr and the original error lost.

I understand that "maskError" happens after useErrorHandler, I am just trying to figgure out where I can access my errors.

Within "maskError" the error has already been converted to a GraphQLerror

    maskedErrors: {
      maskError: (error) => {
        console.log(error.name, 'Its a GraphQLError')
        // And no properties of the original error exists
        console.log(error.originalError.name, 'This is also a GraphQLError...')
        console.log(error.originalError.httpErrorMessage, 'Custom error property is gone')

        return error as Error
      },
    },

Using the useErrorHandler package has the same result.
There are no properties left of the original error that was thrown.

I am using
"graphql-yoga" : "3.0.0-next.8"
"@envelop/core": "^3.0.3"

I am sure the answer is simple, but I think it should be documented how one should catch a custom error thrown in resolvers.

Edit:

After reading up on the documentation, i see that this is intentional.
https://www.the-guild.dev/graphql/yoga-server/tutorial/basic/09-error-handling

I understand the design, and I have to rewrite our error handling to support v3. Which is fine.

I did however like the idea of throwing my custom erros from my resolver integrations and having a single place to catch them all.
It gave me a central integration to catch and log to external services, and I could control how to mask my errors from there.

Explicit is however better than implicit, so I just have to move my code around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants