lib/errors.js
function JSONAPIErrorHandler (err, req, res, next) {
  debug('Handling error(s) using custom jsonapi error handler')
  debug('Set Content-Type header to `application/vnd.api+json`')
  res.set('Content-Type', 'application/vnd.api+json')

  var errors = []
  var statusCode = err.statusCode ||
    err.status ||
    statusCodes.INTERNAL_SERVER_ERROR
  debug('Raw error object:', err)

  if (err.details && err.details.messages) {
    debug('Handling error as a validation error.')

    // This block is for handling validation errors.
    // Build up an array of validation errors.
    errors = Object.keys(err.details.messages).map(function (key) {
      return buildErrorResponse(
        statusCode,
        err.details.messages[key][0],
        err.details.codes[key][0],
        err.name,
        { pointer: 'data/attributes/' + key }
      )
    })
  } else if (err.message) {
    // convert specific errors below to validation errors.
    // These errors are from checks on the incoming payload to ensure it is
    // JSON API compliant. If we switch to being able to use the Accept header
    // to decide whether to handle the request as JSON API, these errors would
    // need to only be applied when the Accept header is `application/vnd.api+json`
    var additionalValidationErrors = [
      'JSON API resource object must contain `data` property',
      'JSON API resource object must contain `data.type` property',
      'JSON API resource object must contain `data.id` property'
    ]

    if (additionalValidationErrors.indexOf(err.message) !== -1) {
      debug('Recasting error as a validation error.')
      statusCode = statusCodes.UNPROCESSABLE_ENTITY
      err.code = 'presence'
      err.name = 'ValidationError'
    }

    debug('Handling invalid relationship specified in url')
    if (/Relation (.*) is not defined for (.*) model/.test(err.message)) {
      statusCode = statusCodes.BAD_REQUEST
      err.message = 'Bad Request'
      err.code = 'INVALID_INCLUDE_TARGET'
      err.name = 'BadRequest'
    }

    var errorSource = err.source && typeof err.source === 'object'
      ? err.source
      : {}
    if (errorStackInResponse) {
      // We do not want to mutate err.source, so we clone it first
      errorSource = _.clone(errorSource)
      errorSource.stack = err.stack
    }

    errors.push(
      buildErrorResponse(
        statusCode,
        err.message,
        err.code,
        err.name,
        errorSource,
        err.meta
      )
    )
  } else {
    debug(
      'Unable to determin error type. Treating error as a general 500 server error.'
    )
    // catch all server 500 error if we were unable to understand the error.
    errors.push(
      buildErrorResponse(
        statusCodes.INTERNAL_SERVER_ERROR,
        'Internal Server error',
        'GENERAL_SERVER_ERROR'
      )
    )
  }

  // send the errors and close out the response.
  debug('Sending error response')
  debug('Response Code:', statusCode)
  debug('Response Object:', { errors: errors })
  res.status(statusCode).send({ errors: errors }).end()
}
function JSONAPIErrorHandler (err, req, res, next) {
  debug('Handling error(s) using custom jsonapi error handler')
  debug('Set Content-Type header to `application/vnd.api+json`')
  res.set('Content-Type', 'application/vnd.api+json')

  var errors = []
  var statusCode = err.statusCode ||
    err.status ||
    statusCodes.INTERNAL_SERVER_ERROR
  debug('Raw error object:', err)

  if (err.details && err.details.messages) {
    debug('Handling error as a validation error.')

    // This block is for handling validation errors.
    // Build up an array of validation errors.
    errors = Object.keys(err.details.messages).map(function (key) {
      return buildErrorResponse(
        statusCode,
        err.details.messages[key][0],
        err.details.codes[key][0],
        err.name,
        { pointer: 'data/attributes/' + key }
      )
    })
  } else if (err.message) {
    // convert specific errors below to validation errors.
    // These errors are from checks on the incoming payload to ensure it is
    // JSON API compliant. If we switch to being able to use the Accept header
    // to decide whether to handle the request as JSON API, these errors would
    // need to only be applied when the Accept header is `application/vnd.api+json`
    var additionalValidationErrors = [
      'JSON API resource object must contain `data` property',
      'JSON API resource object must contain `data.type` property',
      'JSON API resource object must contain `data.id` property'
    ]

    if (additionalValidationErrors.indexOf(err.message) !== -1) {
      debug('Recasting error as a validation error.')
      statusCode = statusCodes.UNPROCESSABLE_ENTITY
      err.code = 'presence'
      err.name = 'ValidationError'
    }

    debug('Handling invalid relationship specified in url')
    if (/Relation (.*) is not defined for (.*) model/.test(err.message)) {
      statusCode = statusCodes.BAD_REQUEST
      err.message = 'Bad Request'
      err.code = 'INVALID_INCLUDE_TARGET'
      err.name = 'BadRequest'
    }

    var errorSource = err.source && typeof err.source === 'object'
      ? err.source
      : {}
    if (errorStackInResponse) {
      // We do not want to mutate err.source, so we clone it first
      errorSource = _.clone(errorSource)
      errorSource.stack = err.stack
    }

    errors.push(
      buildErrorResponse(
        statusCode,
        err.message,
        err.code,
        err.name,
        errorSource,
        err.meta
      )
    )
  } else {
    debug(
      'Unable to determin error type. Treating error as a general 500 server error.'
    )
    // catch all server 500 error if we were unable to understand the error.
    errors.push(
      buildErrorResponse(
        statusCodes.INTERNAL_SERVER_ERROR,
        'Internal Server error',
        'GENERAL_SERVER_ERROR'
      )
    )
  }

  // send the errors and close out the response.
  debug('Sending error response')
  debug('Response Code:', statusCode)
  debug('Response Object:', { errors: errors })
  res.status(statusCode).send({ errors: errors }).end()
}
function JSONAPIErrorHandler ( err , req , res , next ) { debug ( 'Handling error(s) using custom jsonapi error handler' ) debug ( 'Set Content-Type header to `application/vnd.api+json`' ) res . set ( 'Content-Type' , 'application/vnd.api+json' ) var errors = [ ] var statusCode = err . statusCode || err . status || statusCodes . INTERNAL_SERVER_ERROR debug ( 'Raw error object:' , err ) if ( err . details && err . details . messages ) { debug ( 'Handling error as a validation error.' ) // This block is for handling validation errors. // Build up an array of validation errors. errors = Object . keys ( err . details . messages ) . map ( function ( key ) { return buildErrorResponse ( statusCode , err . details . messages [ key ] [ 0 ] , err . details . codes [ key ] [ 0 ] , err . name , { pointer : 'data/attributes/' + key } ) } ) } else if ( err . message ) { // convert specific errors below to validation errors. // These errors are from checks on the incoming payload to ensure it is // JSON API compliant. If we switch to being able to use the Accept header // to decide whether to handle the request as JSON API, these errors would // need to only be applied when the Accept header is `application/vnd.api+json` var additionalValidationErrors = [ 'JSON API resource object must contain `data` property' , 'JSON API resource object must contain `data.type` property' , 'JSON API resource object must contain `data.id` property' ] if ( additionalValidationErrors . indexOf ( err . message ) !== - 1 ) { debug ( 'Recasting error as a validation error.' ) statusCode = statusCodes . UNPROCESSABLE_ENTITY err . code = 'presence' err . name = 'ValidationError' } debug ( 'Handling invalid relationship specified in url' ) if ( / Relation (.*) is not defined for (.*) model / . test ( err . message ) ) { statusCode = statusCodes . BAD_REQUEST err . message = 'Bad Request' err . code = 'INVALID_INCLUDE_TARGET' err . name = 'BadRequest' } var errorSource = err . source && typeof err . source === 'object' ? err . source : { } if ( errorStackInResponse ) { // We do not want to mutate err.source, so we clone it first errorSource = _ . clone ( errorSource ) errorSource . stack = err . stack } errors . push ( buildErrorResponse ( statusCode , err . message , err . code , err . name , errorSource , err . meta ) ) } else { debug ( 'Unable to determin error type. Treating error as a general 500 server error.' ) // catch all server 500 error if we were unable to understand the error. errors . push ( buildErrorResponse ( statusCodes . INTERNAL_SERVER_ERROR , 'Internal Server error' , 'GENERAL_SERVER_ERROR' ) ) } // send the errors and close out the response. debug ( 'Sending error response' ) debug ( 'Response Code:' , statusCode ) debug ( 'Response Object:' , { errors : errors } ) res . status ( statusCode ) . send ( { errors : errors } ) . end ( ) }
Our JSON API Error handler.
@public
@memberOf {Errors}
@param {Object} err The error object
@param {Object} req The request object
@param {Object} res The response object
@param {Function} next
@return {undefined}
Our JSON API Error handler .