apache/superset · error · EChartOptionsParseError

parse_error

parse_error

Error message

err.message

What it means

Raised in SlackV1Upgrade.update_recipients when json.loads(recipient.recipient_config_json) throws TypeError or ValueError for a Slack v1 recipient: the stored recipient_config_json column is not parseable JSON (or not a string at all). It aborts the v1→v2 Slack recipient migration before any writes, so recipients remain untouched.

Source

Thrown at superset-frontend/plugins/plugin-chart-echarts/src/utils/safeEChartOptionsParser.ts:421

  }

  const trimmed = input.trim();
  if (!trimmed) {
    return { success: true, data: undefined };
  }

  // Step 1: Parse into AST
  const wrappedInput = `(${trimmed})`;
  let ast: Node & { body: Array<Node & { expression: Node }> };

  try {
    ast = parse(wrappedInput, {
      ecmaVersion: 2020,
      sourceType: 'script',
    }) as Node & { body: Array<Node & { expression: Node }> };
  } catch (error) {
    const err = error as Error & { loc?: { line: number; column: number } };
    throw new EChartOptionsParseError(err.message, 'parse_error', [], err.loc);
  }

  if (
    !ast.body ||
    ast.body.length !== 1 ||
    ast.body[0].type !== 'ExpressionStatement'
  ) {
    throw new EChartOptionsParseError(
      'Input must be a single object literal expression (e.g., { key: value })',
      'parse_error',
    );
  }

  const { expression } = ast.body[0];

  if (expression.type !== 'ObjectExpression') {
    throw new EChartOptionsParseError(
      `Expected an object literal, but got: ${expression.type}`,

View on GitHub (pinned to f4587218dd)

Solutions

  1. Inspect the row: SELECT id, recipient_config_json FROM report_recipient WHERE id = <id>.
  2. Repair the JSON to a valid object with a string 'target' field (or recreate the recipient via the UI).
  3. Re-run the report; the migration will retry the upgrade.

Example fix

-- before: invalid JSON stored
UPDATE report_recipient SET recipient_config_json = '{"target":"#general"}' WHERE id = 7;
-- (was: '{target:#general}' — unquoted keys)
Defensive patterns

Strategy: validation

Validate before calling

import json

def valid_recipient_json(cfg: str) -> bool:
    try:
        json.loads(cfg)
        return True
    except (TypeError, ValueError):
        return False

Type guard

def is_slack_v1_config(value: str) -> bool:
    try:
        parsed = json.loads(value)
    except (TypeError, ValueError):
        return False
    return isinstance(parsed, dict) and isinstance(parsed.get("target"), str)

Try / catch

try:
    command.run()
except NotificationParamException as ex:
    if "Invalid Slack recipient configuration" in str(ex):
        flag_recipient_row_for_repair(recipient_id)

Prevention

When it happens

Trigger: Executing a report with a Slack (v1) recipient whose recipient_config_json holds malformed JSON — hand-edited rows, legacy truncated data, or rows written by an old buggy client. json.loads raises ValueError (bad JSON) or TypeError (None/non-str).

Common situations: Direct DB edits to report_recipient rows; data migrated from a very old Superset version with a different config shape; JSON containing unescaped quotes truncated by column limits.

Related errors


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