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

  1. Convert the input first: Number.parseInt(value, 10) and verify with Number.isInteger.
  2. Pass a full 4-digit positive integer year (e.g. 2026).
  3. Default empty/undefined flag values explicitly instead of letting them become NaN.
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/032e38b1bc7fe29c. Report an issue: GitHub.