Log raw response when Garmin returns non-JSON
All checks were successful
Deploy / deploy (push) Successful in 1m40s

Garmin is returning HTML error pages instead of JSON data. This
change reads the response as text first, checks if it starts with
{ or [, and logs the first 1000 chars of the response body if not.

This will help diagnose what page Garmin is returning (login, captcha,
rate limit, etc).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-15 13:20:28 +00:00
parent 85b535f04a
commit 98293f5ab5
2 changed files with 101 additions and 93 deletions

View File

@@ -72,7 +72,15 @@ export async function fetchHrvStatus(
return "Unknown";
}
const data = await response.json();
const text = await response.text();
if (!text.startsWith("{") && !text.startsWith("[")) {
logger.error(
{ endpoint: "hrv-service", responseBody: text.slice(0, 1000) },
"Garmin returned non-JSON response",
);
return "Unknown";
}
const data = JSON.parse(text);
const status = data?.hrvSummary?.status;
if (status === "BALANCED") {
@@ -120,7 +128,15 @@ export async function fetchBodyBattery(
return { current: null, yesterdayLow: null };
}
const data = await response.json();
const text = await response.text();
if (!text.startsWith("{") && !text.startsWith("[")) {
logger.error(
{ endpoint: "bodyBattery", responseBody: text.slice(0, 1000) },
"Garmin returned non-JSON response",
);
return { current: null, yesterdayLow: null };
}
const data = JSON.parse(text);
const currentData = data?.bodyBatteryValuesArray?.[0];
const current = currentData?.charged ?? null;
@@ -170,7 +186,15 @@ export async function fetchIntensityMinutes(
return 0;
}
const data = await response.json();
const text = await response.text();
if (!text.startsWith("{") && !text.startsWith("[")) {
logger.error(
{ endpoint: "fitnessstats", responseBody: text.slice(0, 1000) },
"Garmin returned non-JSON response",
);
return 0;
}
const data = JSON.parse(text);
const weeklyTotal = data?.weeklyTotal;
if (!weeklyTotal) {