mikebridge opened a new pull request, #44264:
URL: https://github.com/apache/superset/pull/44264
### SUMMARY
`POST /api/v1/dataset/<uuid>/purge` with no body returned **500 `{"message":
"Fatal error"}`** (sc-120966) — and the database-delete refusal's breadcrumb
pointed straight at it, so a database whose only remaining datasets are
soft-deleted looked undeletable without hand-editing rows. The purge flow
itself is healthy: `GET .../purge-impact` → `POST .../purge` with
`{"confirmed_impact_token": <token>}` works end to end.
**Root cause (stack-wide, not one route).** `requires_json` raised
`InvalidPayloadFormatError` — a status-400 `SupersetErrorException` the
app-level handler renders as the proper structured 400 — but 25 endpoints stack
FAB's `@safe` *outside* the decorator, and `safe` converts every
non-`BadRequest` exception into a generic 500 first. Probe-confirmed identical
on `POST /api/v1/chart/`, `/api/v1/dashboard/`, `/api/v1/annotation_layer/`
with no body. Affected stacks found by sweep: `databases.put`;
`datasets.duplicate/purge`; `semantic_layers.configuration_schema/post/put`;
`queries.stop_query`; `charts.post/put`; `explore/permalink.post`;
`explore/form_data.post/put`; `row_level_security.post/put`;
`dashboards.post/put/put_filters/put_chart_customizations/put_colors`;
`dashboards/permalink.post`; `annotation_layers.post/put` (+ nested
annotations); `views/users.update_me`; `sqllab/permalink.post`; `reports.put`.
Unnoticed until now because real clients always send JSON.
**Fix at the single source**: `requires_json` now *returns* the structured
400 response, built with the same serializer the app handler uses
(`json_error_response`), so `@safe` never sees an exception — every stacked
endpoint is fixed at once, and the error envelope stays byte-identical for the
unstacked call sites (the existing `validate_parameters` shape pin passes
unchanged).
**Second part**: the database-delete 422 message said "delete them
permanently once a purge capability ships, or remove the underlying rows
out-of-band" — the purge capability shipped. It now names the real flow (`GET
.../purge-impact` for the token, then `POST .../purge` with it), with restore
as the alternative.
### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
API behavior. Before: body-less purge POST → `500 {"message":"Fatal
error"}`. After: `400` with `errors[0].error_type ==
"INVALID_PAYLOAD_FORMAT_ERROR"`, `"Request is not JSON"`.
### TESTING INSTRUCTIONS
`pytest tests/integration_tests/datasets/api_tests.py -k RequiresJson` — the
reported endpoint (body-less purge of an archived dataset → structured 400)
plus a sibling (`POST /api/v1/chart/` body-less → structured 400) proving the
source-level fix covers every stack. `pytest
tests/integration_tests/databases/api_tests.py -k invalid_payload_format` — the
pre-existing rich-envelope pin for an unstacked endpoint, unchanged.
### ADDITIONAL INFORMATION
- [x] Has associated issue: sc-120966
- [ ] Required feature flags:
- [ ] Changes UI
- [ ] Includes DB Migration (follow approval process in
[SIP-59](https://github.com/apache/superset/issues/13351))
- [ ] Migration is atomic, supports rollback & is backwards-compatible
- [ ] Confirm DB migration upgrade and downgrade tested
- [ ] Runtime estimates and downtime expectations provided
- [ ] Introduces new feature or API
- [ ] Removes existing feature or API
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW
--
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]