ruvnet/RuView · error · ValueError
Non-JSON response from {method} {path} (status {resp.status}
Error message
Non-JSON response from {method} {path} (status {resp.status}): {raw[:200]!r} What it means
SeedClient._request() in scripts/seed_csi_bridge.py issues JSON-over-HTTPS calls (urllib, Bearer token, TLS verification disabled for the bridge's self-signed cert) to the Cognitum Seed REST API. When the server responds with a 2xx status but the body fails json.loads, it raises ValueError including the method, path, status, and the first 200 raw bytes. A non-JSON body almost always means the URL reached something other than the Seed API.
Source
Thrown at scripts/seed_csi_bridge.py:240
timeout: int = 10, auth: bool = True) -> dict:
"""Issue an HTTP request and return parsed JSON.
Raises urllib.error.URLError on connection failure,
urllib.error.HTTPError on non-2xx status, and
ValueError on non-JSON response body.
"""
url = f"{self.base_url}{path}"
data = json.dumps(body).encode() if body is not None else None
headers = {"Content-Type": "application/json"}
if auth:
headers["Authorization"] = f"Bearer {self.token}"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, context=self.ctx, timeout=timeout) as resp:
raw = resp.read()
try:
return json.loads(raw)
except (json.JSONDecodeError, ValueError) as exc:
raise ValueError(
f"Non-JSON response from {method} {path} "
f"(status {resp.status}): {raw[:200]!r}"
) from exc
def ingest(self, vectors: list[tuple[int, list[float]]]) -> dict:
"""Ingest vectors into the RVF store."""
return self._request("POST", "/api/v1/store/ingest", {"vectors": vectors})
def query(self, vector: list[float], k: int = 5) -> dict:
"""Query kNN for a vector."""
return self._request("POST", "/api/v1/store/query", {"vector": vector, "k": k})
def compact(self) -> dict:
"""Trigger store compaction."""
return self._request("POST", "/api/v1/store/compact")
def status(self) -> dict:
"""Get device status."""View on GitHub (pinned to 4685618388)
Solutions
- Reproduce with curl and inspect the body: `curl -k -H 'Authorization: Bearer <token>' -d '{"k":1}' <base_url>/api/v1/store/query` — the first 200 bytes in the error already tell you what answered
- Fix base_url to the exact host:port of the Seed bridge (no trailing slash needed; the client rstrips it)
- If a reverse proxy fronts the bridge, add routing so /api/v1/* reaches it and errors stay JSON
- Confirm the deployment actually serves the /api/v1/store/* routes at that URL
Example fix
# before
client = SeedClient("https://10.0.0.1", token) # 10.0.0.1 is the router admin UI -> HTML 200
# after
client = SeedClient("https://10.0.0.1:8443", token) # actual Seed bridge port Defensive patterns
Strategy: try-catch
Validate before calling
# Probe that the endpoint speaks JSON before bulk ingesting:
resp = client._request("POST", "/api/v1/store/query", {"vector": [0.0] * 128, "k": 1}) # one cheap call first Type guard
def is_seed_api_response(payload: bytes) -> bool:
import json
try:
json.loads(payload)
return True
except (json.JSONDecodeError, ValueError):
return False Try / catch
try:
result = client.ingest(vectors)
except ValueError as e:
# e message embeds status + first 200 raw bytes: read it to identify HTML proxy pages
raise SystemExit(f"Seed bridge not speaking JSON — check base_url/port: {e}") from e
except urllib.error.URLError as e:
raise SystemExit(f"Seed bridge unreachable: {e}") from e Prevention
- Verify base_url host:port with a single curl -k query before starting a bulk ingest
- The client disables TLS verification for self-signed certs — make sure you are not silently hitting a different HTTPS host
- Keep the /api/v1 prefix intact and confirm the deployment serves JSON on error paths too
When it happens
Trigger: POST /api/v1/store/ingest or /api/v1/store/query where base_url points at a wrong host/port serving HTML (router admin page, reverse-proxy error page, captive portal), the server returns an empty 200 body, or a redirect lands on a login page that answers 200 with HTML.
Common situations: Wrong port in the base_url; an nginx/ingress in front that returns a styled 200/3xx page for unknown routes; the API deployed at a subpath while the client assumes root; token flow changed so the server returns a plain-text response instead of JSON.
Related errors
- Calibration bundle {path} missing key {key!r}
- manifest is not valid JSON: {e}
- manifest must be an object with a 'markers' array
- duplicate marker ids: {sorted(dupes)}
- Failed to load domain configuration: {e}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/a09a6726050cdb0e.
Report an issue: GitHub.