MagicMirrorOrg/MagicMirror · error
${error.message}
Error message
${error.message} What it means
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).
Source
Thrown at js/server_functions.js:143
});
const response = await undici.fetch(url, { dispatcher, headers: headersToSend });
if (response.ok) {
for (const header of expectedReceivedHeaders) {
const headerValue = response.headers.get(header);
if (header) res.set(header, headerValue);
}
const arrayBuffer = await response.arrayBuffer();
res.send(Buffer.from(arrayBuffer));
} else {
throw new Error(`Response status: ${response.status}`);
}
}
} catch (error) {
if (process.env.mmTestMode !== "true") {
Log.error(`Error in CORS request: ${error}`);
}
res.status(500).json({ error: error.message });
}
}
/**
* Gets headers and values to attach to the web request.
* @param {string} url - The url containing the headers and values to send.
* @returns {object} An object specifying name and value of the headers.
*/
function getHeadersToSend (url) {
const headersToSend = { "User-Agent": getUserAgent() };
const headersToSendMatch = new RegExp("sendheaders=(.+?)(&|$)", "g").exec(url);
if (headersToSendMatch) {
const headers = headersToSendMatch[1].split(",");
for (const header of headers) {
const keyValue = header.split(":");
if (keyValue.length !== 2) {
throw new Error(`Invalid format for header ${header}`);
}View on GitHub (pinned to 4b4a59534f)
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)
Example fix
// before sendheaders=Authorization // after sendheaders=Authorization:Bearer%20<token>
Defensive patterns
Strategy: try-catch
Validate before calling
// validate header params before building the request
const pairs = headerString.split(",");
if (pairs.some(p => p.split(":").length !== 2)) throw new Error("sendheaders entries must be name:value");
// optionally preflight upstream: curl -I <upstream-url> Type guard
function isCorsProxy500(body) {
return typeof body === "object" && body !== null && typeof body.error === "string";
} Try / catch
try {
const r = await fetch(proxyUrl);
if (!r.ok) {
const { error } = await r.json();
throw new Error(`CORS proxy: ${error}`); // e.g. 'Response status: 401'
}
} catch (e) {
Log.error(`Feed fetch failed: ${e.message}`);
// retry later / show placeholder UI
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Forbidden: domain not in corsDomainWhitelist
- ${this.logContext}${this.#shortenUrl()} - ${message} Retry #
- response.statusText
AI-assisted analysis of MagicMirrorOrg/MagicMirror@4b4a59534f (2026-08-31).
Data as JSON: /api/errors/c639a64abda0d05c.
Report an issue: GitHub.