apache/superset · error · SupersetApiError

Unknown Error

Error message

Unknown Error

What it means

Raised by extra_validator (superset/databases/schemas.py:273) when the Database API extra field is non-empty but not parseable JSON. extra carries connection tuning options (engine_params, metadata_params, schema_cache_timeout, etc.) as a JSON string; marshmallow validation fails with HTTP 400 and the underlying json.JSONDecodeError message before any DB engine is constructed.

Source

Thrown at superset-frontend/packages/superset-ui-core/src/query/api/v1/handleError.ts:42

export type ErrorInput = string | Error | Response | SupersetApiErrorPayload;

/**
 * Handle API request errors, convert to consistent Superset API error.
 * @param error the catched error from SupersetClient.request(...)
 */
export default async function handleError(error: ErrorInput): Promise<never> {
  // already a Superset error
  if (error instanceof SupersetApiError) {
    throw error;
  }
  // string is the error message itself
  if (typeof error === 'string') {
    throw new SupersetApiError({ message: error });
  }
  // JS errors, normally happens before request was sent
  if (error instanceof Error) {
    throw new SupersetApiError({
      message: error.message || 'Unknown Error',
      originalError: error,
    });
  }

  let errorJson;
  let originalError;
  let errorMessage = 'Unknown Error';
  let status: number | undefined;
  let statusText: string | undefined;

  // catch HTTP errors
  if (error instanceof Response) {
    const { status: responseStatus, statusText: responseStatusText } = error;
    status = responseStatus;
    statusText = responseStatusText;
    errorMessage = `${status} ${statusText}`;
    try {

View on GitHub (pinned to f4587218dd)

Solutions

  1. Build extra as a dict and serialize with json.dumps() instead of string concatenation or repr()
  2. Lint the payload locally: json.loads(extra) must succeed before sending
  3. Check the error's %(msg)s detail — it names the line/column of the first JSON syntax error

Example fix

// before (frontend)
body.extra = `{ engine_params: { pool_size: 5 } }`;  // unquoted keys -> 400

// after
body.extra = JSON.stringify({ engine_params: { pool_size: 5 } });
Defensive patterns

Strategy: validation

Validate before calling

import json

extra_obj = {"engine_params": {"pool_size": 5}}
payload["extra"] = json.dumps(extra_obj)  # never hand-built strings
json.loads(payload["extra"])  # assert round-trip

Type guard

function isExtraJson(extra: string): boolean {
  try { JSON.parse(extra); return true; } catch { return false; }
}

Try / catch

if resp.status_code == 400 and "cannot be decoded by JSON" in resp.text:
    # resp body carries the JSONDecodeError position; fix the payload at that offset

Prevention

When it happens

Trigger: POST/PUT /api/v1/database with extra built via Python repr or f-string templating that breaks quoting; extra containing NaN/Infinity literals (invalid JSON); copy-pasting the YAML form of extra from superset config docs directly into the API payload.

Common situations: Converting a config-file TSQL/CATALOGS-style extra dict to the REST API format and forgetting json.dumps; injecting secrets into extra via string concatenation that leaves unescaped quotes; version upgrades where extra keys changed shape and scripts send hand-built JSON strings.

Related errors


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