Unable to respond with a custom error payload through the Kibana NP

Within the Kibana NP (Node.js), the following methods are provided through dependency injection in the route handlers for the Response Object.

{
    ok: [Function: ok],
    accepted: [Function: accepted],
    noContent: [Function: noContent],
    redirected: [Function: redirected],
    badRequest: [Function: badRequest],
    unauthorized: [Function: unauthorized],
    forbidden: [Function: forbidden],
    notFound: [Function: notFound],
    conflict: [Function: conflict],
    internalError: [Function: internalError],
    customError: [Function: customError],
    custom: [Function: custom] 
}

It's not possible to use either the "customError" or "custom" method containing a response code >= 400 <= 600 together with a custom payload. The only property available is "message" and it must contain only a string.

 return responseObj.custom({
    statusCode: error.statusCode,
    body: 
    {
      message: error.message,
      details: error.detailsArray,
      errorObject: error.errorObject,
    }
 });

In essence, the "custom" methods don't actually expose full control over the reply. If the framework requires a particular shape for error payloads, is there at least some way to tap into the underlying HAPI response object to circumvent this limitation?

That's an expected behavior. Kibana server endpoints are meant to be used and consumed by the Kibana UI. On the client-side, we are doing some checks implicitly from within the 'core' platform when an error is send back from the server to the client, which is one of the reasons why we are expecting an homogeneous format for our server->client errors structure, and are enforcing it in our server-side routing API that is exposed to plugins.

The only (highly discouraged) workaround would be to use a Stream or a Buffer as the body when returning your custom error, as we are not doing any sanity check around these kind of response formats. Note that if (I think that) it would be working with our current master version, it could break at any time in the future.

return res.custom({
   statusCode,
   body: Buffer.from(JSON.stringify(myResponseObject), 'utf8')
})

You might need to specify the content-type using the headers option.

The favored option to preserve our server->client error structure would be to use the attributes property of the body instead:

return res.customError({
    statusCode,
    body: {
        message: e.message,
        attributes: myErrorObject,
    },
});

it would then be accessible on the client-side via (assuming you are using the core.http service as it should be done in KP plugins)

try {
    await core.http.post(...)
} catch(e) {
  const myErrorObject = e.body.attributes;
}
1 Like

Thanks for the quick reply... and BTW, cool name :). Yes the e.body.attributes is the proper solution. I forgot to mention that I had tried it before but the data was filtered. However I must have either... (a) made a typo ... or ... (b) put the attributes property in the wrong place.

In case it helps others, you can see that the Kibana platform silently filters out invalid attributes. The system will also dig into the message property and, if it's of type object, will extract a message.message string (if exists). This is approach accounts for the possibility of providing a new Error('message') (exception object) rather than just a message string.

Response Syntax

return response.customError({
  statusCode: 405,
  body: 
  {
    message: {
      message: 'error.message.custom',
      attributes: {
        detailsArr: [{test1: 'one', test2: 'two'}]
      },
    },
    attributes: {
      detailsArr2: [{test3: 'three', test4: 'four'}]
    },
    attribues: {
      detailsArr3: [{test5: 'five', test6: 'six'}]
    },
  },
  attributes: {
    detailsArr4: [{test7: 'seven', test8: 'eight'}]
  },
});

Response Payload

{
  "statusCode": 405,
  "error": "Method Not Allowed",
  "message": "error.message.custom",
  "attributes": {
    "detailsArr2": [
      {
        "test3": "three",
        "test4": "four"
      }
    ]
  }
}

It seems like you're not using typescript? We highly recommend that you use typescript for writing your plugin, it will make it a lot easier to integrate with the plugin API's. There are a lot of places in Kibana where we will silently ignore invalid parameters because we rely on typescript to detect this.

In your own code you can always decide to use any if you don't care about typesafety.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.