{"record":{"id":"aedfd6a380727fdc","repo":"jackwener/OpenCLI","slug":"error-aedfd6","errorCode":null,"errorMessage":"定时时间必须晚于当前时间","messagePattern":"定时时间必须晚于当前时间","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/wechat-channels/publish.js","lineNumber":99,"sourceCode":"\nfunction parseTimeoutSeconds(raw) {\n  const timeout = raw == null || raw === '' ? 600 : Number(raw);\n  if (!Number.isInteger(timeout) || timeout < 30) {\n    throw new ArgumentError('--timeout must be an integer >= 30 seconds');\n  }\n  return timeout;\n}\n\nfunction parseScheduleDate(raw) {\n  if (!raw) return null;\n  const dt = typeof raw === 'number'\n    ? new Date(raw < 1e12 ? raw * 1000 : raw)\n    : new Date(String(raw));\n  if (Number.isNaN(dt.getTime())) {\n    throw new ArgumentError(`无法解析定时时间: ${raw}`);\n  }\n  if (dt.getTime() <= Date.now()) {\n    throw new ArgumentError('定时时间必须晚于当前时间');\n  }\n  return dt;\n}\n\nfunction parseBooleanFlag(raw) {\n  return raw === true || raw === 'true' || raw === '1' || raw === 1;\n}\n\nfunction remainingMs(deadline, label) {\n  const left = deadline - Date.now();\n  if (left <= 0) {\n    throw new CommandExecutionError(`${label}超时，请增加 --timeout 后重试`);\n  }\n  return left;\n}\n\nfunction submitSucceeded({ isDraft, finalUrl, successMsg }) {\n  const msg = String(successMsg || '');","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wechat-channels/publish.js#L81-L117","documentation":"After successfully parsing the schedule date, parseScheduleDate throws ArgumentError if the time is not strictly after Date.now(). Publishing schedules in the past are rejected by the workflow, so the check fails fast before any UI automation runs.","triggerScenarios":"Passing a timestamp that is already in the past; computing the value with seconds when the code compared against a shifted clock; a long-running script where the schedule time elapsed between computing it and invoking the command.","commonSituations":"Reusing an old schedule timestamp from config; forgetting timezone offset so local time is interpreted as UTC (or vice versa) and lands in the past; re-running a command hours later with the same arguments.","solutions":["Choose a schedule time at least a few minutes in the future.","Verify timezone handling — prefer ISO strings with explicit offsets like +08:00.","Regenerate the timestamp at invocation time rather than reading it from cached config."],"exampleFix":"// before\nnode publish.js --schedule 1756000000000   // past timestamp\n// after\nnode publish.js --schedule $(($(date +%s) + 3600))000   // now + 1h, in ms","handlingStrategy":"validation","validationCode":"const dt = new Date(scheduleRaw);\nif (dt.getTime() <= Date.now()) {\n  throw new Error('Schedule time must be in the future');\n}","typeGuard":"function isFutureDate(v) {\n  return new Date(v).getTime() > Date.now();\n}","tryCatchPattern":"try {\n  await publish({ schedule: scheduleRaw });\n} catch (e) {\n  if (/定时时间必须晚于当前时间/.test(e.message)) {\n    console.error('Regenerate the timestamp; the cached one is in the past');\n  }\n  throw e;\n}","preventionTips":["Generate the schedule timestamp at invocation time, never from cached config.","Add a buffer of a few minutes over 'now'.","Double-check timezone offsets so intended local times do not land in the past."],"tags":["cli","argument-validation","schedule"],"backgroundTag":"date-in-the-past","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}