Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't NestJS GraphQL validation errors placed in the error message field?

Tags:

nestjs

I'm seeing some class-validator errors in an unexpected location. I would expect a more convenient format for dealing with errors, but perhaps I'm unaware of some graphQL tricks for dealing with objects in the extensions field...

While running NestJS sample/23-graphql-code-first, I see the following in the GraphQL playground:

With input:

  addRecipe(newRecipeData: {
    description: "too short"
    title: "this field should fail for being too long"
    ingredients: ["normal"]

  }) {
    title
  }
}

I am returned:

  "errors": [
    {
      "message": "Bad Request Exception",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "addRecipe"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "response": {
            "statusCode": 400,
            "message": [
              "title must be shorter than or equal to 30 characters",
              "description must be longer than or equal to 30 characters"
            ],
            "error": "Bad Request"
          },
          "status": 400,
          "message": "Bad Request Exception",
          "stacktrace": [
            "Error: Bad Request Exception",
            "    at ValidationPipe.exceptionFactory nest/sample/23-graphql-code-first/node_modules/@nestjs/common/pipes/validation.pipe.js:78:20)",
          ...
          ]
        }
      }
    }
  ],
  "data": null
}

These errors are deeply nested, and "Bad Request Exception" is not so useful. Is this working as intended?

like image 916
Calvin Flegal Avatar asked Apr 05 '20 16:04

Calvin Flegal


2 Answers

The best solution is based on this official comment: creates your own formatError or formatResponse function.

I just used in this project on GitHub and it worked fine!

The change needs to be added to src/app.module.ts, by default.

My Sample:

    import { GraphQLError, GraphQLFormattedError } from 'graphql';
    
    GraphQLModule.forRoot({
      autoSchemaFile: true,
      debug: false,
      formatError: (error: GraphQLError) => {
        const graphQLFormattedError: GraphQLFormattedError = {
          message: error?.extensions?.exception?.response?.message || error?.message,
        };
        return graphQLFormattedError;
      },
    }),

And now, I'm getting a formatted error response from GraphQL:

{
  "errors": [
    {
      "message": [
        "firstName must be longer than or equal to 1 characters",
        "lastName must be longer than or equal to 1 characters"
      ]
    }
  ],
  "data": null
}
like image 125
Leonardo Gomes Avatar answered Oct 03 '22 02:10

Leonardo Gomes


When you use Validation pipe you can change that behaviour:

app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: errors => new BadRequestException(errors), // TODO: Use graphql errors instead
      forbidUnknownValues: true,
    }),
  );
like image 24
Joao Silva Avatar answered Oct 03 '22 04:10

Joao Silva