eschutho opened a new pull request, #44404:
URL: https://github.com/apache/superset/pull/44404
### SUMMARY
`_validate_report_extra` in `superset/commands/report/base.py` reads
`extra.dashboard.anchor` from a report/alert schedule's `extra` field. That
field is an untyped marshmallow `Dict` (`superset/reports/schemas.py`: `extra =
fields.Dict(dump_default=None)`), so an API caller can send **any** JSON value
for `anchor`, not just a string.
The code does:
```python
if anchor := dashboard_state.get("anchor"):
try:
anchor_list: list[str] = json.loads(anchor)
if _invalid_tab_ids := set(anchor_list) - set(position_data.keys()):
invalid_tab_ids.update(_invalid_tab_ids)
except json.JSONDecodeError:
...
```
### PROBLEM
`json.loads()` requires a `str`/`bytes`/`bytearray`. When `anchor` is a
non-string scalar (int, float, bool), `json.loads(anchor)` raises a raw
**`TypeError`**, which is **not** a subclass of `json.JSONDecodeError`
(`JSONDecodeError` is a `ValueError`; `TypeError` is unrelated). A related gap:
when `anchor` is a string that parses to a non-iterable scalar (e.g. `"42"` →
`42`), `set(anchor_list)` also raises `TypeError`. Neither is caught by `except
json.JSONDecodeError`.
The uncaught `TypeError` propagates out of `_validate_report_extra` →
`validate()` → `CreateReportScheduleCommand.run()` /
`UpdateReportScheduleCommand.run()`. The REST API layer
(`superset/reports/api.py`) only catches
`ReportScheduleInvalidError`/`ReportScheduleNotFoundError`/`ReportScheduleCreateFailedError`,
so this surfaces as an opaque **500** instead of the **422** validation
response every other malformed-input case in this same method produces.
### FIX
Widen the `except` to also catch `TypeError`:
```python
except (json.JSONDecodeError, TypeError):
```
Both failure modes then fall through to the existing branch and are
collected as a `ValidationError` on the `extra` field, yielding a proper 422.
This mirrors an existing, correct precedent in the same file family:
`superset/commands/report/execute.py` already reads the exact same
`extra.dashboard.anchor` value and catches `(json.JSONDecodeError, TypeError)`.
The validation-time sibling in `base.py` simply never got the same treatment —
the same sibling-site-drift pattern as #42401.
### TESTING INSTRUCTIONS
- Added `test_validate_report_extra_anchor_non_string_type` in
`tests/unit_tests/commands/report/create_test.py` (`"extra": {"dashboard":
{"anchor": 42}}`), asserting one `ValidationError` on the `extra` field.
Confirmed it **raises `TypeError` on pre-fix code** and **passes after the
fix**.
- Full file green: `pytest tests/unit_tests/commands/report/create_test.py`
→ 14 passed.
- `ruff check` and `ruff format --check` clean on both changed files.
### ADDITIONAL INFORMATION
- [ ] Has associated issue:
- [ ] Required feature flags:
- [ ] Changes UI
- [ ] Includes DB Migration (follow approval process in
[SIP-59](https://github.com/apache/superset/issues/13351))
- [ ] Introduces new feature or API
- [ ] Removes existing feature or API
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]