{"record":{"id":"a73cbf1bc14c6b6b","repo":"gethomepage/homepage","slug":"failed-fetching-action","errorCode":null,"errorMessage":"Failed fetching '${action}'","messagePattern":"Failed fetching '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/widgets/fritzbox/proxy.js","lineNumber":31,"sourceCode":"  const params = {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"text/xml; charset='utf-8'\",\n      SoapAction: `urn:schemas-upnp-org:service:${service}:1#${action}`,\n    },\n    body:\n      \"<?xml version='1.0' encoding='utf-8'?>\" +\n      \"<s:Envelope s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>\" +\n      \"<s:Body>\" +\n      `<u:${action} xmlns:u='urn:schemas-upnp-org:service:${service}:1' />` +\n      \"</s:Body>\" +\n      \"</s:Envelope>\",\n  };\n  const apiUrl = `${apiBaseUrl}/igdupnp/control/${servicePath}`;\n  const [status, , data] = await httpProxy(apiUrl, params);\n  if (status !== 200) {\n    logger.debug(`HTTP ${status} performing SoapRequest for ${service}->${action}`, data);\n    throw new Error(`Failed fetching '${action}'`);\n  }\n  const response = {};\n  try {\n    const jsonData = JSON.parse(xml2json(data));\n    const responseElements = jsonData?.elements?.[0]?.elements?.[0]?.elements?.[0]?.elements || [];\n    responseElements.forEach((element) => {\n      response[element.name] = element.elements?.[0].text || \"\";\n    });\n  } catch (e) {\n    logger.debug(`Failed parsing ${service}->${action} response:`, data);\n    throw new Error(`Failed parsing '${action}' response`);\n  }\n\n  return response;\n}\n\nexport default async function fritzboxProxyHandler(req, res) {\n  const { group, service, index } = req.query;","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/gethomepage/homepage/blob/b6dca1ae033e613d8e692f9a161a3cc53a5a2857/src/widgets/fritzbox/proxy.js#L13-L49","documentation":"Thrown by the Fritz!BOX SOAP helper when a SOAP action request to the TR-064 style /igdupnp/control/ endpoint returns any non-200 status. The widget speaks UPnP/SOAP to the router; a non-200 means the router rejected the request before any XML body could be returned or parsed.","triggerScenarios":"Wrong service path or action name for the router firmware (404/500), UPnP/TR-064 disabled in the Fritz!Box web UI (403/404), the configured URL is not the Fritz!Box or points at the wrong interface, or the router requires authentication that the request does not satisfy (401).","commonSituations":"Fritz!Box firmware update moved/removed a TR-064 service; UPnP not enabled under Heimnetz > Netzwerkeinstellungen; base URL using https where the control endpoint is http (or vice versa); widget pointed at a repeater or mesh node instead of the main router that exposes the service.","solutions":["Enable UPnP / TR-064 in the Fritz!Box UI (Heimnetz > Netzwerkeinstellungen > Statusinformationen über UPnP).","Confirm the base URL points at the main Fritz!Box (typically fritz.box on the LAN), not a mesh satellite.","Match the scheme/port the control endpoint expects; the SOAP helper uses http on port 49000 for igdupnp by default.","Check the debug log line logged just before the throw (HTTP ${status} ...) to see whether it is 404 (wrong service path), 401 (auth), or 500 (firmware).","After a Fritz!OS upgrade, verify the service/action names still exist for your model."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify TR-064 is reachable on the expected control port before SOAP calls.\nasync function preflightFritzbox(base) {\n  const u = new URL(base);\n  const res = await fetch(`${u.protocol}//${u.hostname}:49000/igdupnp/control/WANCommonIFC1`, { method: \"HEAD\" });\n  if (!res.ok && res.status !== 405) throw new Error(`Fritz!Box UPnP control not reachable (HTTP ${res.status})`);\n  return true;\n}","typeGuard":"function isFritzboxWidgetConfigured(w) {\n  return Boolean(w && typeof w.url === \"string\" && /^https?:\\/\\//.test(w.url));\n}","tryCatchPattern":"try {\n  return await soapRequest(base, service, action);\n} catch (err) {\n  if (/Failed fetching/.test(err.message)) {\n    res.status(502).json({ error: \"Fritz!Box unreachable\", hint: \"enable UPnP/TR-064\" });\n  } else {\n    throw err;\n  }\n}","preventionTips":["Keep UPnP/TR-064 enabled in the Fritz!Box UI and avoid disabling it during maintenance windows.","Point the widget at the main router, never a mesh satellite that lacks the service.","After every Fritz!OS upgrade, re-run the widget to catch renamed services."],"tags":["network","fritzbox","soap","upnp","router","widget"],"backgroundTag":null,"analyzedSha":"b6dca1ae033e613d8e692f9a161a3cc53a5a2857","analyzedAt":"2026-08-13T04:48:44.121Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}