Return 400 for invalid precoder_type or M_ant<K on /api/mimo/compute - #687
Merged
Merged
Conversation
Previously any ValueError from compute_mimo_scene_with_bodies was caught as a generic 500, including user-facing validation errors raised by the precoder code (e.g. "M_ant (M) must be >= K (K) for ZF precoding" from precoders.zf, or "Unknown precoder type: X" from compute_precoder). Those are user input errors — a 400 tells the frontend exactly what the caller sent wrong. Validate upfront so compute is never reached with a bad precoder choice. Keeps the existing 500-on-Exception path for genuine internal failures (tested by test_compute_exception_returns_500 with RuntimeError). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rwydaegh
added a commit
that referenced
this pull request
Apr 20, 2026
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rwydaegh
added a commit
that referenced
this pull request
Apr 20, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
3 tasks
rwydaegh
added a commit
that referenced
this pull request
Apr 20, 2026
## Summary Install `StrictJSONProvider` on the Flask app so `NaN` / `Infinity` / `-Infinity` in JSON request bodies are rejected at decode time with a 400, instead of slipping past every scalar-float field's `math.isfinite` guard and either crashing downstream or silently propagating into numeric pipelines. Python's stdlib `json` accepts those literals by default as a non-standard RFC 8259 extension; overriding `parse_constant` at the provider level is a single choke point for the whole API surface. ## Why The QA/feature/code-review agents have been shipping one `isfinite`/`isnan` guard PR after another (#668, #670, #675, #685, #687, #693, #694, #698, #701, #707…), each patching a new scalar field on a new route. Whack-a-mole. This replaces the pond with the drain. ## Changes - `src/aegis/viewer/server/_app.py` — `StrictJSONProvider` subclass of `DefaultJSONProvider`, installed in `create_app`. Only `loads` is overridden so routes that intentionally emit NaN (masked spatial averaging) are unaffected on the output side. - `src/aegis/viewer/routes/_helpers.py` — `get_json_dict` now distinguishes empty body (returns `{}`) from parse failure (returns 400 with the parser's message), so provider rejections surface as 400 instead of silently falling through to route defaults. - `tests/test_viewer_strict_json_nonfinite.py` — 37-case regression matrix covering 12 routes × 3 literals (NaN / Infinity / -Infinity) + nested-NaN + happy-path sanity. - Two existing per-field NaN tests relaxed (`test_power_dbm_nan_rejected`, `test_freq_nan_rejected`) to accept either the legacy field-level message or the new parser-level message — the protection now fires earlier. ## Test plan - [x] `pytest tests/test_viewer_strict_json_nonfinite.py tests/test_viewer_non_dict_body_guards.py` — 68/68 pass - [x] `pytest tests/ -m "not slow" --deselect <network-flaky-overpass>` — 2842 pass, 32 skipped - [x] `ruff check` / `ruff format --check` on touched files — clean
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/api/mimo/computecatchall atmimo.py:374-376wraps every exception fromcompute_mimo_scene_with_bodiesas HTTP 500, including user-input ValueErrors raised by the precoder code.M_ant < KraisesValueError(\"M_ant (M) must be >= K (K) for ZF precoding\")atprecoders.py:44, and any unknownprecoder_typeraisesValueError(\"Unknown precoder type: ...\")atprecoders.py:148.precoder_typeandM_ant >= Kupfront and returns 400 with a specific message before invoking compute. Generic Exception path still returns 500 (test_compute_exception_returns_500 preserved).Test plan
ruff checkandruff format --checkclean🤖 Generated with Claude Code