alibaba/arthas · error · Error

Unsupported dataSource format ${format}

Error message

Unsupported dataSource format ${format}

What it means

Thrown by the flame-graph Web Component's genFrames() while rendering, when this.$dataSource.format is not exactly 'line' or 'tree'. Note the setter normalizes format with toLowerCase() for validation but stores the ORIGINAL dataSource object, so a format like 'Line' or 'TREE' passes the setter yet fails here because genFrames compares with === against the lowercase literals. It is a defensive guard that also catches direct mutation of $dataSource.format after assignment.

Source

Thrown at labs/arthas-jfr-frontend/public/flame-graph/flame-graph-class.js:479

  genFrames() {
    this.$root.clear();
    this.$stackTraceMaxDepth = 0;
    this.$totalWeight = 0;
    this.$totalWeightOfBaseline1 = 0;
    this.$totalWeightOfBaseline2 = 0;

    if (this.$dataSource) {
      let format = this.$dataSource.format;
      if (format === 'line') {
        this.genFramesFromLineData();
      } else if (format === 'tree') {
        if (this.$$reverse) {
          console.warn("Tree format data doesn't support reverse");
        }
        this.genFramesFromTreeData();
      } else {
        throw new Error(`Unsupported dataSource format ${format}`);
      }
    }

    this.$root.sort();

    this.$information = this.$$diff
      ? {
          totalWeight: this.$totalWeight,
          totalWeightOfBaseline1: this.$totalWeightOfBaseline1,
          totalWeightOfBaseline2: this.$totalWeightOfBaseline2
        }
      : {
          totalWeight: this.$totalWeight
        };

    this.$root.text = this.$$rootTextGenerator(this.$dataSource, this.$information);
  }

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Normalize the format to a lowercase 'line' or 'tree' before assigning: dataSource.format = String(dataSource.format).trim().toLowerCase().
  2. Patch genFrames() to read this.$dataSource.format.toLowerCase() so the render path matches the setter's validation (apply to BOTH public/ and src/components/ copies).
  3. Ensure the value assigned is exactly the string 'line' or 'tree' and is never mutated after the setter runs.

Example fix

// before
el.dataSource = { format: 'Tree', data: tree };
// throws: Unsupported dataSource format Tree

// after
el.dataSource = { format: 'tree', data: tree };
// or normalize defensively
const ds = { ...raw, format: String(raw.format).trim().toLowerCase() };
el.dataSource = ds;
Defensive patterns

Strategy: validation

Validate before calling

function normalizeDataSource(ds) {
  if (!ds || typeof ds.format !== 'string') return null;
  const f = ds.format.trim().toLowerCase();
  return (f === 'line' || f === 'tree') ? Object.assign({}, ds, { format: f }) : null;
}
const safe = normalizeDataSource(raw);
if (safe) el.dataSource = safe; else throw new Error('invalid dataSource format');

Type guard

function isLineOrTreeFormat(ds) {
  return !!ds && typeof ds.format === 'string'
    && ['line', 'tree'].includes(ds.format.trim().toLowerCase());
}

Try / catch

try {
  el.dataSource = raw;
} catch (e) {
  if (/Unsupported dataSource format/.test(e.message)) {
    el.dataSource = Object.assign({}, raw, { format: String(raw.format).trim().toLowerCase() });
  } else throw e;
}

Prevention

When it happens

Trigger: Assigning element.dataSource = { format: 'Line'/'TREE'/' line ' , ... } (any case other than all-lowercase, or with surrounding whitespace); mutating this.$dataSource.format to an invalid value then calling render(); bypassing the dataSource setter and writing this.$dataSource directly.

Common situations: Backend/JFR service returns format with different casing than the component expects; data reused from a config file that capitalizes 'Tree'; the same vendored library is duplicated under public/flame-graph/ and src/components/FlameGraph/ so a fix in one copy does not fix the other.

Related errors


AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14). Data as JSON: /api/errors/024c423384086030. Report an issue: GitHub.