{"record":{"id":"6ee52f6c1663ecdf","repo":"MagicMirrorOrg/MagicMirror","slug":"invalid-grid-point-data","errorCode":null,"errorMessage":"Invalid grid point data","messagePattern":"Invalid grid point data","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"defaultmodules/weather/providers/weathergov.js","lineNumber":138,"sourceCode":"\t\tconst timeoutId = setTimeout(() => controller.abort(), 120000); // 120 second timeout - DNS can be slow\n\n\t\ttry {\n\t\t\tconst pointsResponse = await fetch(pointsUrl, {\n\t\t\t\tsignal: controller.signal,\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": \"MagicMirror\",\n\t\t\t\t\tAccept: \"application/geo+json\"\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (!pointsResponse.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch grid point: HTTP ${pointsResponse.status}`);\n\t\t\t}\n\n\t\t\tconst pointsData = await pointsResponse.json();\n\n\t\t\tif (!pointsData || !pointsData.properties) {\n\t\t\t\tthrow new Error(\"Invalid grid point data\");\n\t\t\t}\n\n\t\t\t// Extract location name\n\t\t\tconst relLoc = pointsData.properties.relativeLocation?.properties;\n\t\t\tif (relLoc) {\n\t\t\t\tthis.locationName = `${relLoc.city}, ${relLoc.state}`;\n\t\t\t}\n\n\t\t\t// Store forecast URLs\n\t\t\tthis.forecastURL = `${pointsData.properties.forecast}?units=si`;\n\t\t\tthis.forecastHourlyURL = `${pointsData.properties.forecastHourly}?units=si`;\n\t\t\tthis.forecastGridDataURL = pointsData.properties.forecastGridData;\n\t\t\tthis.observationStationsURL = pointsData.properties.observationStations;\n\n\t\t\t// Step 2: Get observation station URL\n\t\t\tconst stationsResponse = await fetch(this.observationStationsURL, {\n\t\t\t\tsignal: controller.signal,\n\t\t\t\theaders: {","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/MagicMirrorOrg/MagicMirror/blob/4b4a59534f7da01e4030e46029fe9dd649a7675e/defaultmodules/weather/providers/weathergov.js#L120-L156","documentation":"After the points request succeeds, #fetchWeatherGovURLs expects pointsData.properties. If the JSON body lacks properties (or is not JSON/an error envelope), the provider cannot derive forecast URLs and throws \"Invalid grid point data\".","triggerScenarios":"api.weather.gov returns 200 with an unexpected body: an API error/limit JSON, an HTML error page that still parsed, or an NWS schema change removing/renaming properties.","commonSituations":"Hitting api.weather.gov rate limits that return 200 with an error body via some proxies/CDNs; edge locations where the API returns an empty property set; running a stale provider against an updated NWS API.","solutions":["Log pointsData before the throw to see what was actually returned.","Retry later if NWS is degraded — transient payloads can lack properties.","Verify the request URL (api.weather.gov/points/{lat},{lon}) returns properties in a browser.","Update MagicMirror — providers are fixed when NWS changes its schema."],"exampleFix":"// before\nif (!pointsData || !pointsData.properties) {\n  throw new Error(\"Invalid grid point data\");\n}\n// after — include the body for diagnosis\nif (!pointsData || !pointsData.properties) {\n  throw new Error(`Invalid grid point data: ${JSON.stringify(pointsData).slice(0, 200)}`);\n}","handlingStrategy":"type-guard","validationCode":"// pre-flight the exact endpoint the provider will call\nconst r = await fetch(`https://api.weather.gov/points/${lat},${lon}`, { headers: { \"User-Agent\": \"MagicMirror\" } });\nconst j = await r.json();\nif (!j?.properties) throw new Error(\"points endpoint lacks properties — NWS degraded or rate limited\");","typeGuard":"function hasGridPoint(d) {\n  return !!d && typeof d === \"object\" && !!d.properties\n    && typeof d.properties.forecast === \"string\";\n}","tryCatchPattern":"try {\n  await provider.initialize();\n} catch (err) {\n  if (err.message === \"Invalid grid point data\") {\n    Log.warn(\"weathergov: unusable grid point payload — retrying later\");\n    scheduleRetry(10 * 60_000);\n  } else { throw err; }\n}","preventionTips":["Respect NWS api.weather.gov rate limits (pool requests, long updateInterval).","Keep MagicMirror updated so provider parsers track NWS schema changes.","Log full response bodies on failure to distinguish error envelopes from schema drift."],"tags":["api","schema-validation","weather","http"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"4b4a59534f7da01e4030e46029fe9dd649a7675e","analyzedAt":"2026-08-31T21:49:42.591Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}