Skip to content

Commit a8e7d19

Browse files
viditchess64claude
andauthored
fix(viewer): surface health status from non-2xx /agentmemory/health responses (#1046)
* fix(viewer): surface health status from non-2xx /agentmemory/health responses The health endpoint intentionally returns HTTP 503 when status is "critical" (src/triggers/api.ts), with a valid JSON body describing the degraded state. The viewer's shared api() fetch helper treated any non-ok response as a hard failure and discarded the body, returning null - so renderDashboard's `h.status || 'unknown'` fallback always showed "unknown" for a critical backend instead of "critical". Parse and return the JSON body on non-ok responses too (falling back to null only if the body isn't valid JSON), so the dashboard reflects the real health status regardless of the HTTP status code used to carry it. Fixes #1019 Signed-off-by: Vidit Gujrathi <223816573+viditchess64@users.noreply.github.com> * fix(viewer): log non-2xx JSON parse failures at debug level Address CodeRabbit review: don't silently swallow the parse error when a non-2xx response body isn't valid JSON - log it at debug level to help diagnose unexpected content types. Signed-off-by: Vidit Gujrathi <223816573+viditchess64@users.noreply.github.com> * fix(viewer): restore non-2xx -> null contract in api(), special-case health Per review: changing the shared api() helper to return parsed bodies on non-2xx responses broke callers that treat null as "request failed" (e.g. loadGraph's disabled/error state). Restore the null contract as the default and let only the health call opt in via readErrorBody, since /agentmemory/health intentionally responds 503 with a valid JSON body when status is critical (#1019). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Signed-off-by: Vidit Gujrathi <223816573+viditchess64@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 6761a99 commit a8e7d19

1 file changed

Lines changed: 15 additions & 2 deletions

File tree

src/viewer/index.html

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,11 +1244,24 @@ <h1>agentmemory</h1>
12441244
headers.Authorization = 'Bearer ' + viewerToken;
12451245
}
12461246
var fetchOpts = Object.assign({}, opts || {}, { headers: headers });
1247+
var readErrorBody = fetchOpts.readErrorBody;
1248+
delete fetchOpts.readErrorBody;
12471249
var res = await fetch(url, fetchOpts);
12481250
if (!res.ok) {
12491251
if (res.status === 401) showViewerAuthPrompt();
12501252
console.warn('[viewer] API ' + (fetchOpts.method || 'GET') + ' ' + path + ' returned ' + res.status);
1251-
return null;
1253+
// Non-2xx responses resolve to null so callers can keep treating
1254+
// null as "request failed" (e.g. loadGraph's disabled/error state).
1255+
// The health endpoint opts out via readErrorBody: it intentionally
1256+
// responds 503 with a valid JSON body when status is "critical"
1257+
// (see #1019), and the dashboard badge needs that body.
1258+
if (!readErrorBody) return null;
1259+
try {
1260+
return await res.json();
1261+
} catch (parseErr) {
1262+
console.debug('[viewer] API ' + path + ' non-2xx body was not JSON:', parseErr);
1263+
return null;
1264+
}
12521265
}
12531266
hideViewerAuthPrompt();
12541267
return await res.json();
@@ -1344,7 +1357,7 @@ <h1>agentmemory</h1>
13441357
el.innerHTML = '<div class="loading">Loading dashboard...</div>';
13451358
try {
13461359
var results = await Promise.all([
1347-
apiGet('health'),
1360+
api('health', { readErrorBody: true }),
13481361
apiGet('sessions'),
13491362
apiGet('memories?latest=true&limit=500'),
13501363
apiGet('graph/stats'),

0 commit comments

Comments
 (0)