apache/superset · error

Chart ${id} is missing form_data

Error message

Chart ${id} is missing form_data

What it means

In the embedded SDK bootstrap path, every chart entry taken from the dashboard layout must carry a form_data object so the embedded client can build its data query. The code iterates chartEntries from the layout and throws when an entry is not an object or lacks the form_data key. This guards against a corrupted or hand-edited layout where a chart slot has no associated form data.

Source

Thrown at superset-frontend/src/embedded/utils.ts:117

    if (!slice || !hasChartStateConverter(slice.viz_type)) {
      return false;
    }

    if (chartId !== undefined && numericId !== chartId) {
      return false;
    }

    return true;
  });

  const payloadPromises = chartEntries.map(async ([id, chart]) => {
    const numericId = Number(id);
    const slice = sliceEntities[id];

    try {
      if (!chart || typeof chart !== 'object' || !('form_data' in chart)) {
        throw new Error(`Chart ${id} is missing form_data`);
      }

      const formData = getFormDataWithExtraFilters({
        chart: { id: numericId, form_data: (chart as JsonObject).form_data },
        chartConfiguration,
        filters: getAppliedFilterValues(numericId),
        colorScheme,
        colorNamespace,
        sliceId: numericId,
        nativeFilters,
        allSliceIds,
        dataMask,
        extraControls: {},
      });

      const chartState = chartStates[id]?.state;
      const baseOwnState = dataMask[id]?.ownState || {};
      const convertedState = chartState

View on GitHub (pinned to f4587218dd)

Solutions

  1. Re-save the dashboard in the Superset UI so the layout and form_data are regenerated consistently.
  2. Fix the layout JSON: every CHART component under positions must have its meta/form_data populated (or the chart re-added via Explore).
  3. If you generate layouts programmatically, copy form_data from the chart's saved slice rather than writing an empty object.
  4. Upgrade/downgrade mismatch: ensure the embedded frontend bundle matches the backend that produced the bootstrap payload.

Example fix

// before
const payloadPromises = chartEntries.map(async ([id, chart]) => {
  if (!chart || typeof chart !== 'object' || !('form_data' in chart)) {
    throw new Error(`Chart ${id} is missing form_data`);
  }
  ...
});

// after
const payloadPromises = chartEntries
  .filter(([id, chart]) => {
    const ok = !!chart && typeof chart === 'object' && 'form_data' in chart;
    if (!ok) logging.warn(`Skipping chart ${id}: missing form_data in layout`);
    return ok;
  })
  .map(async ([id, chart]) => { ... });
Defensive patterns

Strategy: type-guard

Validate before calling

function layoutChartsHaveFormData(
  chartQueries: Record<string, unknown>,
): boolean {
  return Object.values(chartQueries).every(
    c => !!c && typeof c === 'object' && 'form_data' in (c as object),
  );
}

Type guard

function hasFormData(chart: unknown): chart is { form_data: JsonObject } {
  return (
    !!chart &&
    typeof chart === 'object' &&
    'form_data' in chart &&
    typeof (chart as { form_data: unknown }).form_data === 'object'
  );
}

Try / catch

chartEntries.forEach(([id, chart]) => {
  if (!hasFormData(chart)) {
    logging.warn(`Skipping embedded chart ${id}: no form_data in layout`);
    return;
  }
  // build payload
});

Prevention

When it happens

Trigger: Loading an embedded dashboard whose positions/layout JSON contains a chart component without form_data; dashboards whose layout was edited by scripts or migrations that dropped form_data; chart entries keyed by id whose value is null.

Common situations: Imported dashboards with hand-crafted position_json; custom layout tooling that writes chart slots without form data; race where layout from a newer backend version is consumed by an older embedded bundle.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/50ea76b6ac4cdb12. Report an issue: GitHub.