error-handlinggraphqlgraphql-jsaws-appsyncvtl

How to send custom error in AppSync with $util.error


I have a question about AppSync error handling. I would like to send errorInfo object along with the error response and I tried with $util.error. Per the document:

https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html

$util.error(String, String, Object, Object)

Throws a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an errorType field, a data field, and a errorInfo field can be specified. The data value will be added to the corresponding error block inside errors in the GraphQL response. Note: data will be filtered based on the query selection set. The errorInfo value will be added to the corresponding error block inside errors in the GraphQL response. Note: errorInfo will NOT be filtered based on the query selection set.

And here is what my ResponseMappingTemplate look like:

#if( $context.result && $context.result.errorMessage )
  $utils.error($context.result.errorMessage, $context.result.errorType, $context.result.data), $context.result.errorInfo)
#else
  $utils.toJson($context.result.data)
#end

Here is what I did on the resolver:

var result = {
  data: null,
  errorMessage: 'I made this error',
  errorType: 'ALWAYS_ERROR',
  errorInfo: {
    errorCode: 500,
    validations: [
      {
        fieldName: '_',
        result: false,
        reasons: [
          'Failed! Yay!'
        ]
      }
    ],
  }
};
callback(null, result);

And here is what I see in CloudWatch log:

{
    "errors": [
        "CustomTemplateException(message=I made this error, errorType=ALWAYS_ERROR, data=null, errorInfo={errorCode=500, validations=[{fieldName=_, result=false, reasons=[Failed! Yay!]}]})"
    ],
    "mappingTemplateType": "Response Mapping",
    "path": "[getError]",
    "resolverArn": "arn:aws:appsync:ap-southeast-1:....",
    "context": {
        "arguments": {},
        "result": {
            "errorMessage": "I made this error",
            "errorType": "ALWAYS_ERROR",
            "errorInfo": {
                "errorCode": 500,
                "validations": [
                    {
                        "fieldName": "_",
                        "result": false,
                        "reasons": [
                            "Failed! Yay!"
                        ]
                    }
                ]
            }
        },
        "stash": {},
        "outErrors": []
    },
    "fieldInError": true
}

And here is what I got in the response:

{
  "data": {
    "getError": null
  },
  "errors": [
    {
      "path": [
        "getError"
      ],
      "data": null,
      "errorType": "ALWAYS_ERROR",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "I made this error"
    }
  ]
}

Notice that errorInfo is null and I some how got CustomTemplateException. I suspect that is because of the 4th parameter to $utils.error. But I don’t know why. Could anyone help to point out the error or tell me whether sending custom errorInfo is possible


Solution

  • Turn out that I used the code from some tutorial which is not up to date. There are 2 versions of the Resolver Mapping Template: 2018-05-29 and 2017-02-28. So I need to change the template version to 2018-05-29 for it to work.

    RequestMappingTemplate: |
      {
        "version": "2018-05-29",
        "operation": "Invoke",
        "payload": {
          "field": "getError",
          "arguments":  $utils.toJson($context.arguments)
        }
      }
    

    See the changes between 2 versions here: https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-changelog.html#changing-the-version-on-a-function