apache/superset · error · Error
Unsupported whisker type: ${whiskerOptions}
Error message
Unsupported whisker type: ${whiskerOptions} What it means
Raised by encrypted_extra_validator in superset/databases/schemas.py when the encrypted_extra field submitted to the Database REST API is non-empty but fails json.loads. Superset stores encrypted_extra (driver-specific secrets like credentials_params) as a JSON string, so any non-JSON payload is rejected with a marshmallow ValidationError before the DAO layer runs. The API turns this into an HTTP 400 with the JSONDecodeError detail appended to the message.
Source
Thrown at superset-frontend/packages/superset-ui-chart-controls/src/operators/boxplotOperator.ts:52
const { groupby, whiskerOptions } = formData;
if (whiskerOptions) {
let whiskerType: BoxPlotQueryObjectWhiskerType;
let percentiles: [number, number] | undefined;
const percentileMatch = PERCENTILE_REGEX.exec(whiskerOptions as string);
if (whiskerOptions === 'Tukey' || !whiskerOptions) {
whiskerType = 'tukey';
} else if (whiskerOptions === 'Min/max (no outliers)') {
whiskerType = 'min/max';
} else if (percentileMatch) {
whiskerType = 'percentile';
percentiles = [
parseInt(percentileMatch[1], 10),
parseInt(percentileMatch[2], 10),
];
} else {
throw new Error(`Unsupported whisker type: ${whiskerOptions}`);
}
return {
operation: 'boxplot',
options: {
whisker_type: whiskerType,
percentiles,
groupby: ensureIsArray(groupby).map(getColumnLabel),
metrics: ensureIsArray(queryObject.metrics).map(getMetricLabel),
},
};
}
return undefined;
};
View on GitHub (pinned to f4587218dd)
Solutions
- Serialize the value with json.dumps() (or JSON.stringify on the frontend) before sending it as encrypted_extra
- Validate the string with json.loads() locally first; the exception message includes the exact JSONDecodeError position
- If you intended no encrypted extra, send null or omit the field entirely rather than a malformed string
Example fix
# before
payload = {"encrypted_extra": str({"credentials_params": {"user": "bob"}})} # Python repr -> 400
# after
import json
payload = {"encrypted_extra": json.dumps({"credentials_params": {"user": "bob"}})} Defensive patterns
Strategy: validation
Validate before calling
import json
def valid_json_string(v: str | None) -> bool:
if v is None or v == "":
return True
try:
json.loads(v)
return True
except json.JSONDecodeError:
return False
assert valid_json_string(payload.get("encrypted_extra")), "encrypted_extra must be valid JSON" Type guard
def isJsonString(v: unknown): boolean {
if (v == null || v === "") return true;
try { JSON.parse(v as string); return true; } catch { return false; }
} Try / catch
resp = requests.post(url, json=payload)
if resp.status_code == 400 and "cannot be decoded by JSON" in resp.text:
raise ValueError(f"encrypted_extra not valid JSON: {resp.text}") from None Prevention
- Always build encrypted_extra/extra with json.dumps or JSON.stringify, never repr or template strings
- Round-trip check in CI: any fixture that posts to /api/v1/database passes json.loads on its extra fields
When it happens
Trigger: POST /api/v1/database/ or PUT /api/v1/database/<id> with a body whose encrypted_extra is a bare string, unquoted key, trailing comma, or Python dict literal (single quotes) instead of valid JSON; also passing an already-encrypted binary blob or an empty string with stray whitespace characters.
Common situations: Scripts that build encrypted_extra via Python repr() instead of json.dumps(), pasting YAML/INI fragments into the field, or frontend forms serializing the object lazily. Also hit after upgrades when the encrypted_extra payload format was restructured and old tooling sends the previous shape.
Related errors
- Unknown Error
- Found invalid orderby options
- JSON not valid
- Please provide both time bounds (Since and Until)
- All values must be numeric
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/43ae6964b0280bd2.
Report an issue: GitHub.