affaan-m/ECC · error · Error
Invalid now timestamp: ${now}
Error message
Invalid now timestamp: ${now} What it means
Thrown by renderDashboard when options.now is provided but Date.parse(now) returns NaN. When omitted, now defaults to new Date().toISOString() which is always valid, so the error only fires on an explicit bad value.
Source
Thrown at scripts/lib/skill-evolution/dashboard.js:335
for (const version of skill.versions) {
const date = version.created_at ? version.created_at.slice(0, 10) : '-';
const reason = version.reason || '-';
lines.push(` v${version.version} \u2500\u2500 ${date} \u2500\u2500 ${reason}`);
}
}
}
return {
text: panelBox('Version History', lines, width),
data: { skills: skillVersions },
};
}
function renderDashboard(options = {}) {
const now = options.now || new Date().toISOString();
const nowMs = Date.parse(now);
if (Number.isNaN(nowMs)) {
throw new Error(`Invalid now timestamp: ${now}`);
}
const dashboardOptions = { ...options, now };
const records = tracker.readSkillExecutionRecords(dashboardOptions);
const skillsById = health.discoverSkills(dashboardOptions);
const report = health.collectSkillHealth(dashboardOptions);
const summary = health.summarizeHealthReport(report);
const panelRenderers = {
'success-rate': () => renderSuccessRatePanel(records, report.skills, dashboardOptions),
'failures': () => renderFailureClusterPanel(records, dashboardOptions),
'amendments': () => renderAmendmentPanel(skillsById, dashboardOptions),
'versions': () => renderVersionTimelinePanel(skillsById, dashboardOptions),
};
const selectedPanel = options.panel || null;
if (selectedPanel && !VALID_PANELS.has(selectedPanel)) {
throw new Error(`Unknown panel: ${selectedPanel}. Valid panels: ${Array.from(VALID_PANELS).join(', ')}`);View on GitHub (pinned to 01e15490f0)
Solutions
- Omit options.now to use the current time, or pass a strict ISO 8601 string (new Date().toISOString()).
- Validate with Number.isNaN(Date.parse(now)) before passing.
- If accepting user input, parse and re-serialize: new Date(input).toISOString().
Example fix
// before
renderDashboard({ now: userInput }); // userInput = '2025-31-12'
// after
renderDashboard({ now: new Date(userInput).toISOString() }); Defensive patterns
Strategy: validation
Validate before calling
function safeNow(now) {
const v = now || new Date().toISOString();
if (Number.isNaN(Date.parse(v))) throw new TypeError('now is not a date');
return v;
}
renderDashboard({ now: safeNow(opts.now) }); Type guard
function isIsoTimestamp(v) {
return typeof v === 'string' && !Number.isNaN(Date.parse(v));
} Try / catch
try {
renderDashboard({ now });
} catch (err) {
if (/Invalid now timestamp/.test(err.message)) renderDashboard({}); // drop bad now
else throw err;
} Prevention
- Omit options.now unless you need a fixed point in time (tests, replays).
- Always pass new Date().toISOString() rather than locale strings.
- Validate user-supplied timestamps at the boundary, not at the API call.
When it happens
Trigger: Calling renderDashboard({ now: 'yesterday' }), renderDashboard({ now: '12/31/25' }) with a locale format some engines reject, or renderDashboard({ now: someUndefinedVar }) where the var is a non-empty garbage string. Empty string is falsy and falls back to the default, so it does not trigger.
Common situations: Forwarding a user-typed date string without validation; passing a Date object instead of its ISO string (Date.parse(dateObj) works, but inconsistent across engines); timezone/offset formatting that produces an unparseable token.
Related errors
- ${label} must be an ISO-8601 timestamp.
- Unknown panel: ${selectedPanel}. Valid panels: ${Array.from(
- Invalid now timestamp: ${now}
- recorded_at must be an ISO timestamp
- ECC_PROJECT_DIR must be a child path within /workspace.
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/4ac15f43d6f9f2aa.
Report an issue: GitHub.