grafana/grafana · error · Error
Variables is not an array
Error message
Variables is not an array
What it means
Required-field check: variables must be an array. V2 stores variables as a list (each entry is a typed variable spec), unlike V1's object map. Thrown when the transformed dashboard has no variables key or a non-array value.
Source
Thrown at public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts:851
return spec;
}
// Function to know if the dashboard transformed is a valid DashboardV2Spec
export function validateDashboardSchemaV2(dash: unknown): dash is DashboardV2Spec {
if (typeof dash !== 'object' || dash === null || Array.isArray(dash)) {
throw new Error('Dashboard is not an object or is null');
}
// Required properties
if (!('title' in dash) || typeof dash.title !== 'string') {
throw new Error('Title is not a string');
}
if (!('timeSettings' in dash) || typeof dash.timeSettings !== 'object' || dash.timeSettings === null) {
throw new Error('TimeSettings is not an object or is null');
}
if (!('variables' in dash) || !Array.isArray(dash.variables)) {
throw new Error('Variables is not an array');
}
if (!('elements' in dash) || typeof dash.elements !== 'object' || dash.elements === null) {
throw new Error('Elements is not an object or is null');
}
if (!('annotations' in dash) || !Array.isArray(dash.annotations)) {
throw new Error('Annotations is not an array');
}
if (!('layout' in dash) || typeof dash.layout !== 'object' || dash.layout === null) {
throw new Error('Layout is not an object or is null');
}
// Optional properties - only validate if present
if ('description' in dash && dash.description !== undefined && typeof dash.description !== 'string') {
throw new Error('Description is not a string');
}
if ('cursorSync' in dash && dash.cursorSync !== undefined) {
const validCursorSyncValues = ((): string[] => {
const typeValues: DashboardCursorSync[] = ['Off', 'Crosshair', 'Tooltip'];View on GitHub (pinned to ae3104e369)
Solutions
- Ensure getVariables always returns an array (default to [] when there are no variables).
- If migrating from V1, convert the variables object map to the V2 array form before transform.
- Add a unit test for the no-variables case.
- Type the return of getVariables as DashboardV2Variable[] so the compiler catches regressions.
Example fix
// before
if (!('variables' in dash) || !Array.isArray(dash.variables)) {
throw new Error('Variables is not an array');
}
// after — guarantee array in the producer
variables: getVariables(sceneDash, dsReferencesMapping) ?? [], Defensive patterns
Strategy: type-guard
Validate before calling
const vars = getVariables(sceneDash, dsRefs);
if (!Array.isArray(vars)) throw new Error('getVariables must return an array'); Type guard
function isVariablesArray(dash: unknown): dash is { variables: unknown[] } {
return typeof dash === 'object' && dash !== null && 'variables' in dash && Array.isArray((dash as any).variables);
} Try / catch
try { await transformSceneToSaveModelSchemaV2(scene); }
catch (e) {
if (e.message === 'Variables is not an array') reportBug('getVariables returned non-array');
else throw e;
} Prevention
- Type getVariables' return as DashboardV2Variable[].
- Default to [] when there are no variables.
- Unit-test the no-variables transform path.
When it happens
Trigger: getVariables(sceneDash, dsReferencesMapping) returned undefined or an object instead of an array. Happens when the scene has no variables layer or the variables serializer changed shape.
Common situations: Dashboard without any variables (the transformer should still emit []); migration code that returned the V1 object map; refactor of getVariables that dropped the array cast; template variable plugin returning a non-array.
Related errors
- Title is not a string
- TimeSettings is not an object or is null
- Elements is not an object or is null
- Annotations is not an array
- Layout is not an object or is null
AI-assisted analysis of grafana/grafana@ae3104e369 (2026-08-12).
Data as JSON: /api/errors/2e02542e6db93b45.
Report an issue: GitHub.