apache/superset · error · ValidationError
JSON not valid
Error message
JSON not valid
What it means
A marshmallow ValidationError raised by validate_json() in the annotation layer schemas: it attempts json.loads (via superset.utils.json.validate_json) on the json_metadata field of an annotation POST/PUT payload, and when the value is not parseable JSON it converts the JSONDecodeError into 'JSON not valid'. This is field-level input validation on the annotation REST API.
Source
Thrown at superset/annotation_layers/annotations/schemas.py:59
get_delete_ids_schema = {
"type": "array",
"items": {"type": "integer"},
"example": [1, 2, 3],
}
annotation_start_dttm = "The annotation start date time"
annotation_end_dttm = "The annotation end date time"
annotation_layer = "The annotation layer id"
annotation_short_descr = "A short description"
annotation_long_descr = "A long description"
annotation_json_metadata = "JSON metadata"
def validate_json(value: Union[bytes, bytearray, str]) -> None:
try:
json.validate_json(value)
except json.JSONDecodeError as ex:
raise ValidationError("JSON not valid") from ex
class AnnotationPostSchema(Schema):
short_descr = fields.String(
metadata={"description": annotation_short_descr},
required=True,
allow_none=False,
validate=[Length(1, 500)],
)
long_descr = fields.String(
metadata={"description": annotation_long_descr}, allow_none=True
)
start_dttm = fields.DateTime(
metadata={"description": annotation_start_dttm},
required=True,
allow_none=False,
)
end_dttm = fields.DateTime(View on GitHub (pinned to f4587218dd)
Solutions
- Ensure json_metadata is a valid JSON document string: double-quoted keys and strings, no trailing commas, true/false/null literals.
- In Python clients, pass json.dumps(metadata) — never str(metadata) or repr(metadata).
- Validate the string with json.loads() locally before sending the request to fail fast with a better message.
- If the field is optional for your use case, omit json_metadata entirely instead of sending an empty/garbage string.
Example fix
# before
payload = {"short_descr": "note", "json_metadata": str({"color": "red"})}
client.post(url, json=payload) # {'color': 'red'} is not JSON
# after
import json
payload = {"short_descr": "note", "json_metadata": json.dumps({"color": "red"})}
client.post(url, json=payload) Defensive patterns
Strategy: validation
Validate before calling
import json
def json_metadata_field(metadata: dict | None) -> str | None:
if metadata is None:
return None
value = json.dumps(metadata) # raises locally if not serializable
json.loads(value) # round-trip proves it parses
return value Try / catch
except marshmallow.ValidationError as ex:
if "JSON not valid" in str(ex.messages):
# re-serialize metadata properly and retry the request
payload["json_metadata"] = json.dumps(json.loads(payload_raw)) Prevention
- Always json.dumps() metadata objects; never str()/repr().
- Round-trip validate payloads containing JSON-in-string fields before sending.
When it happens
Trigger: POST or PUT to /api/v1/annotation_layer/{layer_id}/annotation/ with json_metadata supplied as a malformed JSON string — unbalanced braces, single quotes instead of double quotes, Python-style None/True literals, trailing commas, or a truncated string. Also passing raw bytes that decode to invalid JSON.
Common situations: Sending dict objects that get str()'d by a client instead of json.dumps()'d; hand-crafted curl payloads with quoting issues where the shell mangles quotes; copying JSON from a Python REPL (single quotes) into a request body; LLM/script-generated payloads with trailing commas.
Related errors
- Unsupported whisker type: ${whiskerOptions}
- Unknown Error
- Request is incorrect
- JSON not valid
- Found invalid orderby options
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/9e7cae9f2fdf7479.
Report an issue: GitHub.