{"record":{"id":"7c031ae97cb67b8d","repo":"jackwener/OpenCLI","slug":"npm-downloads-period-value-is-invalid","errorCode":null,"errorMessage":"npm downloads period \"${value}\" is invalid","messagePattern":"npm downloads period \"(.+?)\" is invalid","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/npm/downloads.js","lineNumber":24,"sourceCode":"import { cli, Strategy } from '@jackwener/opencli/registry';\nimport { ArgumentError, EmptyResultError } from '@jackwener/opencli/errors';\nimport { NPM_API, npmFetch, requirePackageName } from './utils.js';\n\nconst FIXED_PERIODS = new Set(['last-day', 'last-week', 'last-month', 'last-year']);\nconst RANGE_PATTERN = /^(\\d{4}-\\d{2}-\\d{2}):(\\d{4}-\\d{2}-\\d{2})$/;\n\nfunction requirePeriod(value) {\n    const s = String(value ?? 'last-week').trim();\n    if (FIXED_PERIODS.has(s)) return s;\n    const m = RANGE_PATTERN.exec(s);\n    if (m) {\n        const [, start, end] = m;\n        if (new Date(start) > new Date(end)) {\n            throw new ArgumentError(`npm downloads period start ${start} is after end ${end}`);\n        }\n        return `${start}:${end}`;\n    }\n    throw new ArgumentError(\n        `npm downloads period \"${value}\" is invalid`,\n        'Use last-day / last-week (default) / last-month / last-year, or YYYY-MM-DD:YYYY-MM-DD.',\n    );\n}\n\ncli({\n    site: 'npm',\n    name: 'downloads',\n    access: 'read',\n    description: 'Daily download counts for an npm package over a window',\n    domain: 'api.npmjs.org',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'name', positional: true, required: true, help: 'npm package name (e.g. \"react\", \"@vercel/og\")' },\n        { name: 'period', default: 'last-week', help: 'last-day / last-week / last-month / last-year, or YYYY-MM-DD:YYYY-MM-DD' },\n    ],\n    columns: ['rank', 'package', 'day', 'downloads'],","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/npm/downloads.js#L6-L42","documentation":"requirePeriod falls back to this ArgumentError when the period string is neither one of the fixed keywords (last-day/last-week/last-month/last-year) nor a match for RANGE_PATTERN (YYYY-MM-DD:YYYY-MM-DD). The error message includes the offending value and a hint listing all accepted formats.","triggerScenarios":"Passing periods such as '7d', 'week', '2024-01-01' (no end), '2024/01/01:2024/02/01' (slashes instead of dashes), 'last-week:' (malformed range), or an empty string after trimming.","commonSituations":"Using relative ranges like 'last-30-days' that the parser does not support; locale-formatted dates; CLI flag typo (--period last weak); scripts passing human-friendly strings straight through.","solutions":["Use one of the exact keywords: last-day, last-week, last-month, last-year","Use the strict range form YYYY-MM-DD:YYYY-MM-DD, e.g. 2024-01-01:2024-03-31","Normalize relative inputs (e.g. '30d') to a concrete date range before calling the CLI","Follow the hint embedded in the error message for accepted formats"],"exampleFix":"// before\n--period last-30-days\n// after\n--period 2026-07-30:2026-08-29   # or --period last-month","handlingStrategy":"validation","validationCode":"const FIXED = ['last-day','last-week','last-month','last-year'];\nconst RANGE = /^\\d{4}-\\d{2}-\\d{2}:\\d{4}-\\d{2}-\\d{2}$/;\nif (!FIXED.includes(p) && !RANGE.test(p)) throw new Error(`period \"${p}\" invalid; use ${FIXED.join('/')} or YYYY-MM-DD:YYYY-MM-DD`);","typeGuard":"function isNpmPeriod(v){ return ['last-day','last-week','last-month','last-year'].includes(v) || /^\\d{4}-\\d{2}-\\d{2}:\\d{4}-\\d{2}-\\d{2}$/.test(v); }","tryCatchPattern":"try { await run(['npm-downloads', '--period', p]); }\ncatch (e) {\n  if (e instanceof ArgumentError && /is invalid/.test(e.message)) {\n    console.error(e.message, e.hint); // error carries a usage hint\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Use only the four exact keywords or strict YYYY-MM-DD:YYYY-MM-DD ranges","Translate relative ranges like '30d' to concrete dates before invoking","Avoid locale date formats (slashes, DD/MM) — the parser only accepts ISO dashes","Read the hint included in the error message; it lists every accepted format"],"tags":["argument-validation","date-format","npm"],"backgroundTag":"invalid-date-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}