Skip to content

Commit

Permalink
[ESUI] More robust handling of error responses (#96819)
Browse files Browse the repository at this point in the history
* more robust handling of error responses

* added tests and further hardening of how we handle error values
  • Loading branch information
jloleysens authored Apr 13, 2021
1 parent d8b4316 commit b9c4d24
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { errors } from '@elastic/elasticsearch';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { kibanaResponseFactory as response } from 'src/core/server';
import { handleEsError } from './handle_es_error';

const { ResponseError } = errors;

const anyObject: any = {};

describe('handleEsError', () => {
test('top-level reason is an empty string', () => {
const emptyReasonError = new ResponseError({
warnings: [],
meta: anyObject,
body: {
error: {
root_cause: [],
type: 'search_phase_execution_exception',
reason: '', // Empty reason
phase: 'fetch',
grouped: true,
failed_shards: [],
caused_by: {
type: 'too_many_buckets_exception',
reason: 'This is the nested reason',
max_buckets: 100,
},
},
},
statusCode: 503,
headers: {},
});

const { payload, status } = handleEsError({ error: emptyReasonError, response });

expect(payload.message).toEqual('This is the nested reason');
expect(status).toBe(503);
});

test('empty error', () => {
const { payload, status } = handleEsError({
error: new ResponseError({
body: {},
statusCode: 400,
headers: {},
meta: anyObject,
warnings: [],
}),
response,
});

expect(payload).toEqual({
attributes: { causes: undefined, error: undefined },
message: 'Response Error',
});

expect(status).toBe(400);
});

test('unknown object', () => {
expect(() => handleEsError({ error: anyObject, response })).toThrow();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ export const handleEsError = ({
return response.customError({
statusCode,
body: {
message: body.error?.reason ?? error.message ?? 'Unknown error',
message:
// We use || instead of ?? as the switch here because reason could be an empty string
body?.error?.reason || body?.error?.caused_by?.reason || error.message || 'Unknown error',
attributes: {
// The full original ES error object
error: body.error,
error: body?.error,
// We assume that this is an ES error object with a nested caused by chain if we can see the "caused_by" field at the top-level
causes: body.error?.caused_by ? getEsCause(body.error) : undefined,
causes: body?.error?.caused_by ? getEsCause(body.error) : undefined,
},
},
});
Expand Down

0 comments on commit b9c4d24

Please sign in to comment.