{"record":{"id":"c639a64abda0d05c","repo":"MagicMirrorOrg/MagicMirror","slug":"error-message","errorCode":null,"errorMessage":"${error.message}","messagePattern":"\\$\\{error\\.message\\}","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"js/server_functions.js","lineNumber":143,"sourceCode":"\t\t\t});\n\n\t\t\tconst response = await undici.fetch(url, { dispatcher, headers: headersToSend });\n\t\t\tif (response.ok) {\n\t\t\t\tfor (const header of expectedReceivedHeaders) {\n\t\t\t\t\tconst headerValue = response.headers.get(header);\n\t\t\t\t\tif (header) res.set(header, headerValue);\n\t\t\t\t}\n\t\t\t\tconst arrayBuffer = await response.arrayBuffer();\n\t\t\t\tres.send(Buffer.from(arrayBuffer));\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Response status: ${response.status}`);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tif (process.env.mmTestMode !== \"true\") {\n\t\t\tLog.error(`Error in CORS request: ${error}`);\n\t\t}\n\t\tres.status(500).json({ error: error.message });\n\t}\n}\n\n/**\n * Gets headers and values to attach to the web request.\n * @param {string} url - The url containing the headers and values to send.\n * @returns {object} An object specifying name and value of the headers.\n */\nfunction getHeadersToSend (url) {\n\tconst headersToSend = { \"User-Agent\": getUserAgent() };\n\tconst headersToSendMatch = new RegExp(\"sendheaders=(.+?)(&|$)\", \"g\").exec(url);\n\tif (headersToSendMatch) {\n\t\tconst headers = headersToSendMatch[1].split(\",\");\n\t\tfor (const header of headers) {\n\t\t\tconst keyValue = header.split(\":\");\n\t\t\tif (keyValue.length !== 2) {\n\t\t\t\tthrow new Error(`Invalid format for header ${header}`);\n\t\t\t}","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/MagicMirrorOrg/MagicMirror/blob/4b4a59534f7da01e4030e46029fe9dd649a7675e/js/server_functions.js#L125-L161","documentation":"The /cors route wraps all proxied work (header parsing, DNS pinning, fetch, response forwarding) in a try/catch. Any thrown error — including the internal `Response status: <code>` thrown for non-OK upstream responses and 'Invalid format for header ...' from malformed sendheaders — is surfaced as HTTP 500 with `{error: error.message}`. The server log records 'Error in CORS request: ...' (suppressed under mmTestMode=true).","triggerScenarios":"Upstream fetch returns non-2xx (thrown as `Response status: 404/401/...`); malformed sendheaders/expectedheaders params (js/server_functions.js:160 rejects header strings without exactly one ':'); DNS failure or network error during undici.fetch; secret placeholder missing from process.env leaving an unparsable URL.","commonSituations":"Expired API key causing upstream 401/403; dead or renamed feed URL causing 404; sending sendheaders=a:b,c (missing colon); TLS/network errors to the upstream host; testing with mmTestMode so logs are hidden and only the 500 body remains.","solutions":["Read the error.message in the 500 response body — for 'Response status: N', fix the upstream request (URL, auth headers) so the target returns 2xx","Check the MagicMirror server log ('Error in CORS request: ...') for the full stack — run without mmTestMode=true","Fix sendheaders format: comma-separated, each entry strictly 'name:value' with exactly one colon","If upstream requires auth, use **SECRET_*** placeholders with cors set to disabled/allowWhitelist (not allowAll) and ensure the env var is actually set","Verify the target URL is reachable from the server (curl it directly)"],"exampleFix":"// before\nsendheaders=Authorization\n// after\nsendheaders=Authorization:Bearer%20<token>","handlingStrategy":"try-catch","validationCode":"// validate header params before building the request\nconst pairs = headerString.split(\",\");\nif (pairs.some(p => p.split(\":\").length !== 2)) throw new Error(\"sendheaders entries must be name:value\");\n// optionally preflight upstream: curl -I <upstream-url>","typeGuard":"function isCorsProxy500(body) {\n  return typeof body === \"object\" && body !== null && typeof body.error === \"string\";\n}","tryCatchPattern":"try {\n  const r = await fetch(proxyUrl);\n  if (!r.ok) {\n    const { error } = await r.json();\n    throw new Error(`CORS proxy: ${error}`); // e.g. 'Response status: 401'\n  }\n} catch (e) {\n  Log.error(`Feed fetch failed: ${e.message}`);\n  // retry later / show placeholder UI\n}","preventionTips":["Check MagicMirror server logs (disable mmTestMode) for the root cause","Validate sendheaders format strictly (exactly one ':' per pair)","Test upstream URLs with curl before adding to config","Handle 401/404 by refreshing credentials or updating feed URLs","Use **SECRET_*** placeholders with non-allowAll cors modes so auth headers survive"],"tags":["http-500","cors-proxy","upstream-error","fetch"],"backgroundTag":"cors-proxy-upstream-failed","analyzedSha":"4b4a59534f7da01e4030e46029fe9dd649a7675e","analyzedAt":"2026-08-31T21:49:42.591Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}