apache/superset · error · ValueError
python_date_format is an invalid date/timestamp format.
Error message
python_date_format is an invalid date/timestamp format.
What it means
ValueError raised by DatasetDAO._validate_column_date_formats while updating a dataset: a column in the payload carries a non-None `python_date_format` that fails DatasetDAO.validate_python_date_format (a datetime.strptime round-trip check). It fires before super().update() persists anything.
Source
Thrown at superset/daos/dataset.py:447
if "metrics" in attributes:
cls.update_metrics(item, attributes.pop("metrics"))
force_update = True
if force_update:
attributes["changed_on"] = datetime.now()
return super().update(item, attributes)
@classmethod
def _validate_column_date_formats(
cls, property_columns: list[dict[str, Any]]
) -> None:
for column in property_columns:
if column.get("python_date_format") is None:
continue
if not DatasetDAO.validate_python_date_format(column["python_date_format"]):
raise ValueError(
"python_date_format is an invalid date/timestamp format."
)
@classmethod
def _override_columns(
cls, model: SqlaTable, property_columns: list[dict[str, Any]]
) -> None:
"""Replace columns by natural key (``column_name``) — update in place
rather than delete-and-reinsert.
SPIKE (full-Continuum): the previous
delete-and-reinsert pattern produced overlapping shadow rows in
``table_columns_version`` (the same ``column_name`` had a DELETE
shadow at tx N alongside an INSERT shadow at tx N for a fresh PK).
Continuum's ``Reverter`` couldn't unwind this on restore: its flush
ordering inserts the historical row before deleting the live one,
hitting the ``UNIQUE (table_id, column_name)`` constraint mid-flush
(ADR-004 Failure 1).View on GitHub (pinned to f4587218dd)
Solutions
- Convert the format to Python strptime syntax: '%Y-%m-%d %H:%M:%S' etc. (moment-style 'YYYY-MM-DD' is the most common mistake).
- Leave python_date_format null to let Superset infer temporal formatting.
- Validate candidate formats client-side with datetime.strptime(now, fmt) before submitting.
Example fix
# before
columns=[{"column_name": "dt", "python_date_format": "YYYY-MM-DD"}]
# after
columns=[{"column_name": "dt", "python_date_format": "%Y-%m-%d"}] Defensive patterns
Strategy: validation
Validate before calling
from datetime import datetime
def valid_python_date_format(fmt: str | None) -> bool:
if fmt is None:
return True
try:
datetime.now().strftime(fmt) # round-trip sanity
datetime.strptime(datetime.now().strftime(fmt), fmt)
return True
except (ValueError, TypeError):
return False Type guard
import re
def is_strptime_format(fmt: str) -> bool:
# reject common moment/Java-style tokens
return not re.search(r"(?<!%)YYYY|(?<!%)MM|(?<!%)DD|yyyy|dd", fmt) Try / catch
try:
DatasetDAO.update(dataset, {"columns": columns})
except ValueError as ex:
if 'python_date_format' in str(ex):
# fix the offending format tokens and resubmit once
... Prevention
- python_date_format uses strptime codes (%Y %m %d), never moment tokens (YYYY-MM-DD).
- Null the field to use Superset's automatic temporal inference.
- Run a strptime round-trip test on generated format strings in dataset-sync tooling.
When it happens
Trigger: PUT/PATCH /api/v1/dataset/<id> (or column-edit flows) with columns[] entries whose python_date_format is not a valid Python strptime pattern — e.g. 'YYYY-MM-DD' (moment/ISO-style) instead of '%Y-%m-%d', or a typo like '%Y-%m-%'.
Common situations: Confusing Superset's two format dialects: python_date_format expects strptime codes while `db_engine_spec`-side/Java or moment-style tokens ('yyyy-MM-dd') belong elsewhere; integrations writing column payloads generated from JSON Schema examples with moment tokens.
Related errors
- created_by_fk_or_editor only supports 'eq'; got '{c.opr}'
- Dataset parameters are invalid.
- Dataset parameters are invalid.
- Dataset parameters are invalid.
- Cycle detected: {uuid} appears in its ancestry
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/a459438ca9e53088.
Report an issue: GitHub.