{"record":{"id":"aaead26038ed298c","repo":"MagicMirrorOrg/MagicMirror","slug":"invalid-api-response-aaead2","errorCode":null,"errorMessage":"Invalid API response","messagePattern":"Invalid API response","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"defaultmodules/weather/providers/weatherapi.js","lineNumber":212,"sourceCode":"\t\tconst locationParts = [\n\t\t\tresponseData.location.name,\n\t\t\tresponseData.location.region,\n\t\t\tresponseData.location.country\n\t\t]\n\t\t\t.map((value) => `${value}`.trim())\n\t\t\t.filter((value) => value !== \"\");\n\n\t\tif (locationParts.length > 0) {\n\t\t\tthis.locationName = locationParts.join(\", \").trim();\n\t\t}\n\n\t\tif (\n\t\t\t!responseData.location\n\t\t\t|| !responseData.current\n\t\t\t|| !responseData.forecast\n\t\t\t|| !Array.isArray(responseData.forecast.forecastday)\n\t\t) {\n\t\t\tthrow new Error(\"Invalid API response\");\n\t\t}\n\n\t\treturn responseData;\n\t}\n\n\t#parseSunDatetime (forecastDay, key) {\n\t\tconst timeValue = forecastDay?.astro?.[key];\n\t\tif (!timeValue || !forecastDay?.date) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst match = (/^\\s*(\\d{1,2}):(\\d{2})\\s*(AM|PM)\\s*$/i).exec(timeValue);\n\t\tif (!match) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet hour = parseInt(match[1], 10);\n\t\tconst minute = parseInt(match[2], 10);","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/MagicMirrorOrg/MagicMirror/blob/4b4a59534f7da01e4030e46029fe9dd649a7675e/defaultmodules/weather/providers/weatherapi.js#L194-L230","documentation":"#parseResponse validates the shape of the JSON returned by the WeatherAPI.com API. A valid response must contain location, current, forecast, and forecast.forecastday as an array. If any is absent the provider considers the payload unusable and throws \"Invalid API response\".","triggerScenarios":"The API returns 200 with an error JSON body (invalid/expired key, quota exceeded, bad query), a partially empty payload, or a non-standard body (proxy/captive-portal HTML parsed oddly, cached error).","commonSituations":"Free-tier daily quota exhausted; key not yet activated (weatherapi keys need a trial activation); plan downgraded removing forecast access; corporate proxy intercepting requests.","solutions":["Log the raw response body around the throw to see the API's error message (usually an \"error\" object with code/message).","Check your weatherapi.com dashboard for quota/plan limits and key status.","Test the same request URL in a browser/curl to confirm the API response shape.","Ensure no proxy or ad-blocker is rewriting API responses; verify network egress.","If your plan lacks forecast data, upgrade or switch config.type to \"current\"."],"exampleFix":"// before — silent failure hides the API error body\nthrow new Error(\"Invalid API response\");\n// after — surface it\nif (!responseData.location || !responseData.current || !responseData.forecast) {\n  throw new Error(`Invalid API response: ${JSON.stringify(responseData).slice(0, 200)}`);\n}","handlingStrategy":"try-catch","validationCode":"const ok = (d) => d && d.location && d.current && d.forecast && Array.isArray(d.forecast.forecastday);\n// call the API directly first if you suspect plan/quota issues:\n// fetch(`https://api.weatherapi.com/v1/forecast.json?key=${key}&q=${lat},${lon}&days=3`)","typeGuard":"function isWeatherApiResponse(d) {\n  return !!d && typeof d === \"object\"\n    && !!d.location && !!d.current && !!d.forecast\n    && Array.isArray(d.forecast.forecastday);\n}","tryCatchPattern":"try {\n  await provider.initialize();\n} catch (err) {\n  if (err.message === \"Invalid API response\") {\n    Log.error(\"weatherapi returned an unexpected body — check key status/quota at weatherapi.com\");\n    showFallbackWeather();\n  } else { throw err; }\n}","preventionTips":["Monitor your weatherapi.com quota; free tier is 1M calls/month with per-hour caps.","Cache responses and lengthen updateInterval to reduce quota burn.","Alert on the API's own error body (error.code) rather than only on shape failures."],"tags":["api","schema-validation","weather","http"],"backgroundTag":"schema-validation-failed","analyzedSha":"4b4a59534f7da01e4030e46029fe9dd649a7675e","analyzedAt":"2026-08-31T21:49:42.591Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}