diff --git a/packages/grafana-data/src/field/fieldOverrides.test.ts b/packages/grafana-data/src/field/fieldOverrides.test.ts index 4d62d1794df..901fc6d8cc2 100644 --- a/packages/grafana-data/src/field/fieldOverrides.test.ts +++ b/packages/grafana-data/src/field/fieldOverrides.test.ts @@ -252,23 +252,23 @@ describe('applyFieldOverrides', () => { { name: 'value', type: FieldType.number, values: [10, 20] }, ], }); - const f0 = createDataFrame({ - name: 'A', - fields: [ - { - name: 'message', - type: FieldType.string, - values: ['foo'], - }, - { - name: 'frame', - type: FieldType.frame, - values: [f0Internal], - }, - ], - }); it('will apply field overrides to the fields within the frame', () => { + const f0 = createDataFrame({ + name: 'A', + fields: [ + { + name: 'message', + type: FieldType.string, + values: ['foo'], + }, + { + name: 'frame', + type: FieldType.frame, + values: [f0Internal], + }, + ], + }); const withOverrides = applyFieldOverrides({ data: [f0], fieldConfig: { @@ -284,6 +284,38 @@ describe('applyFieldOverrides', () => { expect(withOverrides[0].fields[1].values[0].fields[1].state.range.max).toBe(30); }); + + it('will not crash when some of the nested frames are undefined', () => { + const f0 = createDataFrame({ + name: 'A', + fields: [ + { + name: 'message', + type: FieldType.string, + values: ['foo', 'bar'], + }, + { + name: 'frame', + type: FieldType.frame, + values: [f0Internal, undefined], + }, + ], + }); + expect(() => + applyFieldOverrides({ + data: [f0], + fieldConfig: { + defaults: { + max: 30, + }, + overrides: [], + }, + replaceVariables: (value) => value, + theme: createTheme(), + fieldConfigRegistry: customFieldRegistry, + }) + ).not.toThrow(); + }); }); it('will merge FieldConfig with default values', () => { diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts index cbdf9ba49e8..96d7d403644 100644 --- a/packages/grafana-data/src/field/fieldOverrides.ts +++ b/packages/grafana-data/src/field/fieldOverrides.ts @@ -5,7 +5,7 @@ import { usePrevious } from 'react-use'; import { ThresholdsMode, VariableFormatID } from '@grafana/schema'; import { compareArrayValues, compareDataFrameStructures } from '../dataframe/frameComparisons'; -import { guessFieldTypeForField } from '../dataframe/processDataFrame'; +import { createDataFrame, guessFieldTypeForField } from '../dataframe/processDataFrame'; import { PanelPlugin } from '../panel/PanelPlugin'; import { asHexString } from '../themes/colorManipulator'; import { GrafanaTheme2 } from '../themes/types'; @@ -238,7 +238,11 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra if (field.type === FieldType.frame) { field.values = applyFieldOverrides({ ...options, - data: field.values, + // nested frames can be `undefined` in certain situations, like after `merge` transform due to padding the value array. + // let's replace them with empty frames to avoid errors applying overrides + data: field.values.map( + (nestedFrame: DataFrame | undefined): DataFrame => nestedFrame ?? createDataFrame({ fields: [] }) + ), }); } }