Skip to content

Commit 6fcf871

Browse files
amitpaz1claude
andcommitted
Fix SLO list endpoint: handle JSONB columns returned as strings
asyncpg may return JSONB columns as strings depending on codec registration. Parse safely in both cases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d3a6d85 commit 6fcf871

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

src/lore/server/routes/slo.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,22 @@ def _ts(val) -> Optional[str]:
9191
return str(val)
9292

9393

94+
def _parse_jsonb(val) -> List[Dict[str, Any]]:
95+
"""Safely parse a JSONB column that may come back as str or list."""
96+
if val is None:
97+
return []
98+
if isinstance(val, list):
99+
return val
100+
if isinstance(val, str):
101+
import json as _json
102+
try:
103+
parsed = _json.loads(val)
104+
return parsed if isinstance(parsed, list) else []
105+
except (ValueError, TypeError):
106+
return []
107+
return []
108+
109+
94110
# ── CRUD Endpoints ───────────────────────────────────────────────
95111

96112

@@ -115,7 +131,7 @@ async def list_slos(
115131
metric=r["metric"], operator=r["operator"],
116132
threshold=float(r["threshold"]),
117133
window_minutes=r["window_minutes"], enabled=r["enabled"],
118-
alert_channels=r["alert_channels"] or [],
134+
alert_channels=_parse_jsonb(r.get("alert_channels")),
119135
created_at=_ts(r["created_at"]), updated_at=_ts(r["updated_at"]),
120136
)
121137
for r in rows
@@ -321,7 +337,7 @@ async def list_alerts(
321337
metric_value=float(r["metric_value"]),
322338
threshold=float(r["threshold"]),
323339
status=r["status"],
324-
dispatched_to=r["dispatched_to"] or [],
340+
dispatched_to=_parse_jsonb(r.get("dispatched_to")),
325341
created_at=_ts(r["created_at"]),
326342
)
327343
for r in rows

0 commit comments

Comments
 (0)