grafana/grafana · error · Error

LiveNow is not a boolean

Error message

LiveNow is not a boolean

What it means

Thrown by validateDashboardSchemaV2 (transformSceneToSaveModelSchemaV2.ts:878) when dash.liveNow is present but typeof is not 'boolean'. liveNow is an optional boolean on the V2 spec controlling live (auto-refresh-now) dashboards; the guard rejects stringified booleans or numbers. transformSceneToSaveModelSchemaV2 rewraps the throw as a transform error, aborting the save.

Source

Thrown at public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts:878

    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'];
      return typeValues;
    })();

    if (typeof dash.cursorSync !== 'string' || !validCursorSyncValues.includes(dash.cursorSync)) {
      throw new Error('CursorSync is not a valid value');
    }
  }
  if ('liveNow' in dash && dash.liveNow !== undefined && typeof dash.liveNow !== 'boolean') {
    throw new Error('LiveNow is not a boolean');
  }
  if ('preload' in dash && dash.preload !== undefined && typeof dash.preload !== 'boolean') {
    throw new Error('Preload is not a boolean');
  }
  if ('editable' in dash && dash.editable !== undefined && typeof dash.editable !== 'boolean') {
    throw new Error('Editable is not a boolean');
  }
  if ('links' in dash && dash.links !== undefined && !Array.isArray(dash.links)) {
    throw new Error('Links is not an array');
  }
  if ('tags' in dash && dash.tags !== undefined && !Array.isArray(dash.tags)) {
    throw new Error('Tags is not an array');
  }
  if ('id' in dash && dash.id !== undefined && typeof dash.id !== 'number') {
    throw new Error('ID is not a number');
  }

  // Time settings validation

View on GitHub (pinned to ae3104e369)

Solutions

  1. Coerce the source value with Boolean() (as getLiveNow already does) before building the spec.
  2. Delete the liveNow key when the source value is undefined so the optional-property branch is skipped.
  3. Type the producer against DashboardV2Spec so a non-boolean is caught at compile time.

Example fix

// before
const dash = { ...spec, liveNow: payload.liveNow }; // payload.liveNow === 'true'
// after
const dash = { ...spec, liveNow: payload.liveNow == null ? undefined : Boolean(payload.liveNow) };
Defensive patterns

Strategy: validation

Validate before calling

if ('liveNow' in dash && dash.liveNow !== undefined && typeof dash.liveNow !== 'boolean') {
  throw new Error(`liveNow must be boolean, got ${typeof dash.liveNow}`);
}

Type guard

function isBool(v: unknown): v is boolean { return typeof v === 'boolean'; }
// usage: if (dash.liveNow != null && !isBool(dash.liveNow)) { dash.liveNow = Boolean(dash.liveNow); }

Try / catch

try {
  validateDashboardSchemaV2(dash);
} catch (e) {
  if (String(e).includes('LiveNow')) { dash.liveNow = Boolean((dash as any).liveNow); validateDashboardSchemaV2(dash); }
  else throw e;
}

Prevention

When it happens

Trigger: validateDashboardSchemaV2 receives a dash object whose liveNow is e.g. 'true' (string), 1, or null; this happens when the object was deserialized from JSON/query params that stringified the flag, or when a custom producer omitted the Boolean() coercion that getLiveNow() normally applies.

Common situations: Loading dashboards from URL query strings or REST payloads where booleans arrive as strings; migration code that copies raw fields without coercion; snapshots imported from tools that serialize booleans as 0/1.

Related errors


AI-assisted analysis of grafana/grafana@ae3104e369 (2026-08-12). Data as JSON: /api/errors/62ed0786078a5d18. Report an issue: GitHub.