From a43533ca4462c33ef266245428194f18e6cf60b3 Mon Sep 17 00:00:00 2001 From: ZdenekSrotyr Date: Mon, 4 May 2026 14:04:16 +0200 Subject: [PATCH] =?UTF-8?q?fix(cli):=20#168=20review=20iter=204=20?= =?UTF-8?q?=E2=80=94=20render=20`reason`=20when=20both=20kind+reason=20set?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Devin Review iter #4 caught: `_format_dict` in cli/error_render.py seeded `seen = {"kind", "reason"}` to keep both out of the kv block. But the label line uses only ONE of them (`kind or reason or "error"`), so the other was silently dropped. Quota rejections at app/api/query.py:423 (daily-budget) and 488 (concurrent-slot) emit BOTH keys: `{reason: "daily_byte_cap_exceeded", kind: "daily_bytes", ...}` and `{reason: "concurrent_slot_exceeded", kind: "concurrent_scans", ...}`. Operator only saw `kind` in the label and never the more specific `reason` value. Fix: track which key actually went into the label and skip only that one. The other appears in the kv section. Verified output: Error: daily_bytes (HTTP 429) reason: daily_byte_cap_exceeded current: 99999 ... 8 affected render tests pass. --- cli/error_render.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/cli/error_render.py b/cli/error_render.py index e1c00c2..fe4951c 100644 --- a/cli/error_render.py +++ b/cli/error_render.py @@ -63,11 +63,20 @@ def _detail_dict(body: Any) -> dict | None: def _format_dict(status_code: int, detail: dict) -> str: - """Multi-line render of a recognized typed-error dict.""" - label = detail.get("kind") or detail.get("reason") or "error" + """Multi-line render of a recognized typed-error dict. + + When both `kind` and `reason` are present (e.g. quota rejections at + `app/api/query.py` carry `{reason: "daily_byte_cap_exceeded", + kind: "daily_bytes", ...}`), the label line shows only one — the + other must still appear in the key/value section so its value isn't + silently dropped. Devin Review iter #4 caught this. + """ + label_key = "kind" if detail.get("kind") else ("reason" if detail.get("reason") else None) + label = detail.get(label_key) if label_key else "error" lines: list[str] = [f"Error: {label} (HTTP {status_code})"] - seen: set[str] = {"kind", "reason"} # already in the label line + # Only the key actually used in the label is hidden from the kv block. + seen: set[str] = {label_key} if label_key else set() # Priority keys first for key in _PRIORITY_KEYS: if key in seen: