{"record":{"id":"2e218ebcb81637ca","repo":"gethomepage/homepage","slug":"authorization-failure-getting-data-from-glances-ap","errorCode":null,"errorMessage":"Authorization failure getting data from glances API. Data: ${data.toString()}","messagePattern":"Authorization failure getting data from glances API\\. Data: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"src/pages/api/widgets/glances.js","lineNumber":33,"sourceCode":"  }\n\n  const apiUrl = `${url}/api/${privateWidgetOptions.version}/${endpoint}`;\n  const headers = {\n    \"Accept-Encoding\": \"application/json\",\n  };\n  if (privateWidgetOptions.username && privateWidgetOptions.password) {\n    headers.Authorization = `Basic ${Buffer.from(\n      `${privateWidgetOptions.username}:${privateWidgetOptions.password}`,\n    ).toString(\"base64\")}`;\n  }\n  const params = { method: \"GET\", headers };\n\n  const [status, , data] = await httpProxy(apiUrl, params);\n\n  if (status === 401) {\n    errorMessage = `Authorization failure getting data from glances API. Data: ${data.toString()}`;\n    logger.error(errorMessage);\n    throw new Error(errorMessage);\n  }\n\n  if (status !== 200) {\n    errorMessage = `HTTP ${status} getting data from glances API. Data: ${data.toString()}`;\n    logger.error(errorMessage);\n    throw new Error(errorMessage);\n  }\n\n  return JSON.parse(Buffer.from(data).toString());\n}\n\nexport default async function handler(req, res) {\n  const { index, cputemp: includeCpuTemp, uptime: includeUptime, disk: includeDisks, version } = req.query;\n\n  const privateWidgetOptions = await getPrivateWidgetOptions(\"glances\", index);\n  privateWidgetOptions.version = parseVersionForUrl(version, 3);\n\n  try {","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/gethomepage/homepage/blob/b6dca1ae033e613d8e692f9a161a3cc53a5a2857/src/pages/api/widgets/glances.js#L15-L51","documentation":"Thrown when the upstream Glances instance responds HTTP 401 to Homepage's proxied GET. Homepage treats 401 distinctly from other non-200 statuses because it usually means the configured username/password is wrong or missing for a protected Glances API.","triggerScenarios":"retrieveFromGlancesAPI() builds the request, calls httpProxy(apiUrl, params), and `status === 401`. Occurs when Glances has auth enabled and the widget either sent no credentials or sent wrong ones (Basic auth built from username/password).","commonSituations":"Glances was recently secured with a username/password but the Homepage widget config wasn't updated; password rotated on the Glances side; username has a typo; credentials worked over HTTP but the Glances reverse proxy now strips the Authorization header.","solutions":["In the Glances widget config, set both username and password to match Glances' configured auth.","Confirm Glances actually requires auth — if not, remove the credentials so no Authorization header is sent.","Check that any reverse proxy in front of Glances forwards the Authorization header.","Test the credentials directly: `curl -u user:pass http://glances:61108/api/3/cpu`."],"exampleFix":"// before\nwidget:\n  type: glances\n  url: http://glances:61108\n  username: admin\n  password: wrongpass\n\n// after\nwidget:\n  type: glances\n  url: http://glances:61108\n  username: admin\n  password: correctpass","handlingStrategy":"try-catch","validationCode":"async function canReachGlances(url, creds) {\n  const headers = {};\n  if (creds?.username && creds?.password) {\n    headers.Authorization = 'Basic ' + Buffer.from(`${creds.username}:${creds.password}`).toString('base64');\n  }\n  const res = await fetch(`${url}/api/3/version`, { headers });\n  return res.status !== 401;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await retrieveFromGlancesAPI(options, endpoint);\n} catch (err) {\n  if (/Authorization failure/.test(err.message)) {\n    // surface a user-friendly 'wrong Glances credentials' message\n  }\n  throw err;\n}","preventionTips":["Keep the Glances username/password in sync with the widget config.","Test credentials with curl before pasting them into Homepage.","If Glances is unauthenticated, remove the username/password fields entirely.","Ensure reverse proxies forward the Authorization header."],"tags":["widget","glances","auth","network","http"],"backgroundTag":null,"analyzedSha":"b6dca1ae033e613d8e692f9a161a3cc53a5a2857","analyzedAt":"2026-08-13T04:48:44.121Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}