{"record":{"id":"f419ff70e673a68f","repo":"jackwener/OpenCLI","slug":"wttr-in-returned-no-forecast-for-location","errorCode":null,"errorMessage":"wttr.in returned no forecast for \"${location}\".","messagePattern":"wttr\\.in returned no forecast for \"(.+?)\"\\.","errorType":"error_code","errorClass":"EmptyResultError","httpStatus":null,"severity":"error","filePath":"clis/wttr/forecast.js","lineNumber":46,"sourceCode":"            help: 'Max forecast days (1-3, wttr.in caps the response at 3 days)',\n        },\n    ],\n    columns: [\n        'rank', 'date', 'minTempC', 'maxTempC', 'avgTempC',\n        'minTempF', 'maxTempF', 'avgTempF',\n        'sunHour', 'totalSnowCm', 'uvIndex',\n        'description', 'sunrise', 'sunset',\n    ],\n    func: async (args) => {\n        const location = requireString(args.location, 'location');\n        const days = Number(args.days ?? 3);\n        if (!Number.isInteger(days) || days < 1 || days > 3) {\n            throw new ArgumentError('--days must be an integer between 1 and 3 (wttr.in caps the free-tier forecast at 3 days)');\n        }\n        const body = await wttrFetch(location, 'wttr forecast');\n        const list = Array.isArray(body?.weather) ? body.weather : [];\n        if (!list.length) {\n            throw new EmptyResultError('wttr forecast', `wttr.in returned no forecast for \"${location}\".`);\n        }\n        return list.slice(0, days).map((day, i) => {\n            // wttr.in's day-summary uses the noon hourly slot for \"main\" description.\n            // Index 4 = 12:00 in their 3-hour-step hourly array.\n            const noon = Array.isArray(day.hourly) && day.hourly[4] ? day.hourly[4] : day.hourly?.[0] ?? {};\n            const astro = Array.isArray(day.astronomy) ? day.astronomy[0] : null;\n            return {\n                rank: i + 1,\n                date: day.date ?? null,\n                minTempC: day.mintempC != null ? Number(day.mintempC) : null,\n                maxTempC: day.maxtempC != null ? Number(day.maxtempC) : null,\n                avgTempC: day.avgtempC != null ? Number(day.avgtempC) : null,\n                minTempF: day.mintempF != null ? Number(day.mintempF) : null,\n                maxTempF: day.maxtempF != null ? Number(day.maxtempF) : null,\n                avgTempF: day.avgtempF != null ? Number(day.avgtempF) : null,\n                sunHour: day.sunHour != null ? Number(day.sunHour) : null,\n                totalSnowCm: day.totalSnow_cm != null ? Number(day.totalSnow_cm) : null,\n                uvIndex: day.uvIndex != null ? Number(day.uvIndex) : null,","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wttr/forecast.js#L28-L64","documentation":"This EmptyResultError is thrown when wttr.in responds successfully but its j1 JSON payload contains no `weather` array (or an empty one) for the requested location. It signals a successful HTTP exchange that yielded no forecast data rather than a network or HTTP failure.","triggerScenarios":"wttrFetch returns a body where body.weather is missing, not an array, or []; the command then throws EmptyResultError('wttr forecast', ...).","commonSituations":"wttr.in returning a degenerate 200 response for obscure locations; API schema changes; rate-limited or cached empty responses; typos in location that still geocode to nothing.","solutions":["Retry with a more canonical location string (e.g. 'Paris' or '48.85,2.35')","Check wttr.in availability/rate limiting with curl 'https://wttr.in/Paris?format=j1'","Handle EmptyResultError in your caller and surface a friendly message"],"exampleFix":"// before\nawait forecast({ location: 'Nowhereville XYZ' });\n// after\nawait forecast({ location: 'Paris' }); // or lat,lon pair","handlingStrategy":"try-catch","validationCode":"const body = await wttrFetch(location, 'wttr forecast');\nif (!Array.isArray(body?.weather) || body.weather.length === 0) {\n  throw new Error(`no forecast data for ${location}`);\n}","typeGuard":"function hasForecast(body) {\n  return typeof body === 'object' && body !== null &&\n    Array.isArray(body.weather) && body.weather.length > 0;\n}","tryCatchPattern":"try {\n  result = await forecast({ location });\n} catch (err) {\n  if (err instanceof EmptyResultError) {\n    console.warn(`No forecast for \"${location}\"; try a nearby major city.`);\n  } else throw err;\n}","preventionTips":["Prefer well-known city names or lat,lon coordinates","Check the raw wttr.in response for the location before relying on it","Treat empty weather arrays as an expected outcome and fall back to another provider"],"tags":["empty-result","api-response","forecast"],"backgroundTag":"empty-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}