jackwener/OpenCLI · warning · ArgumentError
${label} 非法:${year},应为正整数
Error message
${label} 非法:${year},应为正整数 What it means
validateYear in clis/mubu/notes.js guards year inputs used by date parsing helpers (parseDate, parseMonth, resolveRange). It throws ArgumentError ('<label> 非法:<year>,应为正整数' — '<label> is invalid: <year>, expected a positive integer') when the value is not an integer or is less than 1. The label names which field failed (e.g. 年份).
Source
Thrown at clis/mubu/notes.js:18
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError } from '@jackwener/opencli/errors';
import { mubuPost, nodesToMarkdown, nodesToText, htmlToText } from './utils.js';
// ── 日期工具 ──────────────────────────────────────────────
function localToday() {
const d = new Date();
return { year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate() };
}
function lastDayOfMonth(year, month) {
return new Date(year, month, 0).getDate();
}
function validateYear(year, label = '年份') {
if (!Number.isInteger(year) || year < 1) {
throw new ArgumentError(`${label} 非法:${year},应为正整数`);
}
}
function validateMonth(month) {
if (!Number.isInteger(month) || month < 1 || month > 12) {
throw new ArgumentError(`月份非法:${month},应为 1-12`);
}
}
function validateDay(year, month, day) {
const maxDay = lastDayOfMonth(year, month);
if (!Number.isInteger(day) || day < 1 || day > maxDay) {
throw new ArgumentError(`日期非法:${year}-${month}-${day}(${year} 年 ${month} 月共 ${maxDay} 天)`);
}
}
function parseDate(s) {
const parts = s.split('-').map(Number);View on GitHub (pinned to 49907e53dc)
Solutions
- Convert the input first: Number.parseInt(value, 10) and verify with Number.isInteger.
- Pass a full 4-digit positive integer year (e.g. 2026).
- Default empty/undefined flag values explicitly instead of letting them become NaN.
- If the value comes from CLI flags, validate with /^\d{4}$/ before calling parseDate/parseMonth/resolveRange.
Example fix
// before
const year = args.year; // '2026' (string) -> ArgumentError
resolveRange(year, ...);
// after
const year = Number.parseInt(args.year, 10);
if (!Number.isInteger(year) || year < 1) throw new Error(`bad year: ${args.year}`);
resolveRange(year, ...); Defensive patterns
Strategy: validation
Validate before calling
function coerceYear(raw, label = '年份') {
const n = typeof raw === 'string' ? Number.parseInt(raw, 10) : raw;
if (!Number.isInteger(n) || n < 1) throw new Error(`${label} must be a positive integer, got: ${raw}`);
return n;
}
// call before parseDate/parseMonth/resolveRange: coerceYear(args.year) Type guard
function isPositiveInteger(v) {
return Number.isInteger(v) && v >= 1;
} Try / catch
try {
const range = resolveRange(year, month);
} catch (e) {
if (/非法:.*应为正整数/.test(e.message)) {
console.error('Year must be a positive integer, e.g. --year 2026');
process.exitCode = 2;
} else { throw e; }
} Prevention
- Convert CLI flags with Number.parseInt(value, 10) before use.
- Require full 4-digit years; reject 2-digit abbreviations.
- Check for undefined/empty flags that coerce to NaN and default them explicitly.
- Reuse validateYear (or a shared isPositiveInteger guard) on every year input path.
When it happens
Trigger: Calling parseDate, parseMonth, or resolveRange with a year that is non-integer (e.g. 2026.5), zero, negative, NaN, or an uncoerced numeric string ('2026') — any value failing Number.isInteger(year) || year < 1.
Common situations: Passing a user-supplied --year string straight from argv without Number conversion; an empty flag producing NaN/undefined; 2-digit years like '26'; negative years from mis-parsed date arithmetic in range queries.
Related errors
- --expiration must be a valid calendar date
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/032e38b1bc7fe29c.
Report an issue: GitHub.