{"record":{"id":"117e440b22e06d62","repo":"jackwener/OpenCLI","slug":"days-must-be-an-integer-between-1-and-3-wttr-in","errorCode":null,"errorMessage":"--days must be an integer between 1 and 3 (wttr.in caps the free-tier forecast at 3 days)","messagePattern":"--days must be an integer between 1 and 3 \\(wttr\\.in caps the free-tier forecast at 3 days\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/wttr/forecast.js","lineNumber":41,"sourceCode":"        },\n        {\n            name: 'days',\n            type: 'int',\n            default: 3,\n            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,","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wttr/forecast.js#L23-L59","documentation":"This ArgumentError is thrown by the wttr forecast command when the --days option is not an integer in the 1-3 range. The wttr.in free-tier API only serves a 3-day forecast payload, so requesting more than 3 days is impossible and requesting 0 or non-integer values is meaningless. The library fails fast client-side before making any network request.","triggerScenarios":"Calling the forecast command with days < 1, days > 3, or a non-integer (e.g. '2.5', 'abc', ''). Number(args.days ?? 3) coerces strings, so '--days abc' becomes NaN and '--days 10' passes the truthiness check but fails the range test.","commonSituations":"Users assuming wttr.in supports 7-day forecasts like other weather APIs; scripts passing an unset or misparsed env var into --days; passing a float from a config file.","solutions":["Pass an integer between 1 and 3, e.g. --days 3","If you need longer ranges, use a different API (wttr.in free tier caps at 3 days)","Default to omitting --days, which defaults to 3"],"exampleFix":"// before\nconst days = Number(args.days ?? 3); // days=7 -> ArgumentError\n// after\nconst days = Math.min(3, Math.max(1, Number.parseInt(args.days ?? 3, 10)));","handlingStrategy":"validation","validationCode":"const days = Number(args.days ?? 3);\nif (!Number.isInteger(days) || days < 1 || days > 3) {\n  throw new Error('--days must be an integer between 1 and 3');\n}","typeGuard":"function isValidDays(v) {\n  const n = Number(v ?? 3);\n  return Number.isInteger(n) && n >= 1 && n <= 3;\n}","tryCatchPattern":"try {\n  result = await forecast({ location, days });\n} catch (err) {\n  if (err instanceof ArgumentError) {\n    console.error(`Invalid --days: ${err.message}`);\n  } else throw err;\n}","preventionTips":["Clamp user input to 1-3 with Math.min/Math.max before passing","Parse with parseInt and validate Number.isInteger","Document the 3-day free-tier cap in your CLI help text"],"tags":["argument-validation","cli","forecast"],"backgroundTag":"invalid-argument-range","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}