gethomepage/homepage · error · Error
Error getting data from Audiobookshelf: ${status}. Data: ${d
Error message
Error getting data from Audiobookshelf: ${status}. Data: ${data.toString()} What it means
Thrown by retrieveFromAPI in the Audiobookshelf proxy when the upstream Audiobookshelf HTTP API returns any non-200 status. The proxy forwards credentials as a Bearer token and expects a 200 with JSON; any other status (auth failure, network error reflected as a 4xx/5xx, or a redirect) is treated as fatal before JSON parsing.
Source
Thrown at src/widgets/audiobookshelf/proxy.js:19
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
import { formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
const proxyName = "audiobookshelfProxyHandler";
const logger = createLogger(proxyName);
async function retrieveFromAPI(url, key) {
const headers = {
"content-type": "application/json",
Authorization: `Bearer ${key}`,
};
const [status, , data] = await httpProxy(url, { headers });
if (status !== 200) {
throw new Error(`Error getting data from Audiobookshelf: ${status}. Data: ${data.toString()}`);
}
return JSON.parse(Buffer.from(data).toString());
}
export default async function audiobookshelfProxyHandler(req, res) {
const { group, service, endpoint, index } = req.query;
if (!group || !service) {
logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
return res.status(400).json({ error: "Invalid proxy service type" });
}
const widget = await getServiceWidget(group, service, index);
if (!widget) {
logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
return res.status(400).json({ error: "Invalid proxy service type" });View on GitHub (pinned to b6dca1ae03)
Solutions
- Verify the Audiobookshelf service URL and that the host is reachable from the Homepage container (curl the same URL with the same token).
- Confirm the API key is valid in Audiobookshelf under Settings > Users and has not expired.
- Check the reverse proxy in front of Audiobookshelf returns 200 for the same path the widget calls.
- Inspect the Homepage debug log; data.toString() in the message often contains the upstream body (HTML error page, JSON error) that pinpoints 401/404/502.
- Ensure the URL template in the widget config resolves to the v1 API path Audiobookshelf expects.
Example fix
// before
if (status !== 200) {
throw new Error(`Error getting data from Audiobookshelf: ${status}. Data: ${data.toString()}`);
}
// after
if (status !== 200) {
throw new Error(`Audiobookshelf ${url} returned HTTP ${status}: ${Buffer.from(data).toString().slice(0, 200)}`);
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight the Audiobookshelf URL and key before the widget polls.
async function checkAudiobookshelf(base, key) {
const res = await fetch(`${base.replace(/\/$/, "")}/api/items?n=1`, {
headers: { Authorization: `Bearer ${key}` },
});
if (!res.ok) throw new Error(`Audiobookshelf pre-flight HTTP ${res.status}`);
return true;
} Type guard
function isAudiobookshelfErrorPayload(v) {
return typeof v === "object" && v !== null && typeof v.error === "string";
} Try / catch
try {
const data = await retrieveFromAPI(url, key);
res.json(data);
} catch (err) {
logger.warn("Audiobookshelf proxy failed for %s: %s", url, err.message);
res.status(502).json({ error: "Audiobookshelf unavailable", detail: err.message });
} Prevention
- Store the Audiobookshelf API key in a secret manager and inject via env var to avoid copy/whitespace errors.
- Add a health-check dependency so Homepage only calls Audiobookshelf when it is reachable.
- Wrap the proxy call so a 5xx upstream becomes a 502 to the dashboard, not a crash.
When it happens
Trigger: Calling the Audiobookshelf /api/... endpoint with an invalid or expired API key (401/403), pointing the widget at the wrong URL so the path 404s, Audiobookshelf behind a reverse proxy returning 502/503, or a typo'd base URL hitting an unrelated server that does not return 200.
Common situations: API key mis-typed or copied with whitespace; base URL configured with a trailing slash or wrong port; Audiobookshelf upgraded and changed an endpoint path; reverse proxy (Traefik/Caddy/Nginx) returning an error page instead of proxying; token lacks permission for the requested endpoint.
Related errors
- Unable to login to Duplicati (status ${status})
- Duplicati request failed for ${endpoint}
- TrueNAS authentication failed
- Authorization failure getting data from glances API. Data: $
- HTTP ${status} getting data from glances API. Data: ${data.t
AI-assisted analysis of gethomepage/homepage@b6dca1ae03 (2026-08-13).
Data as JSON: /api/errors/acf8bebe88d212c0.
Report an issue: GitHub.