affaan-m/ECC · error · Error
Unknown panel: . Valid panels
Error message
Unknown panel: ${selectedPanel}. Valid panels: ${Array.from(VALID_PANELS).join(', ')} What it means
renderDashboard renders one of a fixed set of panels (or all when no panel is given) validated against the VALID_PANELS set. When options.panel names a panel that is not in that set, the dashboard cannot know what to render and throws, listing all valid panel names.
Solutions
- Use a panel name exactly as listed in the error message (e.g. 'amendments', 'versions'), matching lowercase spelling.
- Normalize user input before calling: options.panel = String(raw).trim().toLowerCase().
- Omit options.panel to render the full dashboard with all panels.
- If a needed panel is genuinely missing, update to a library version that includes it or add a panel renderer to VALID_PANELS.
Example fix
// before
renderDashboard({ panel: 'Health' });
// after
const valid = ['amendments', 'versions'];
const panel = String(process.argv[3] || '').trim().toLowerCase();
renderDashboard({ panel: valid.includes(panel) ? panel : undefined }); Defensive patterns
Strategy: validation
Validate before calling
const VALID_PANELS = new Set(['amendments', 'versions']);
const panel = opts.panel ? String(opts.panel).trim().toLowerCase() : null;
if (panel && !VALID_PANELS.has(panel)) throw new Error(`panel must be one of: ${[...VALID_PANELS].join(', ')}`); Type guard
const isValidPanel = (p) => typeof p === 'string' && VALID_PANELS.has(p.trim().toLowerCase());
Try / catch
try {
return renderDashboard({ panel });
} catch (err) {
if (err.message.startsWith('Unknown panel')) {
console.error(err.message); // includes valid panels list
return renderDashboard({});
}
throw err;
} Prevention
- Expose the valid panel names as exported constants and build CLI help text from them.
- Normalize panel input (trim + lowercase) before passing it on.
- Omit the panel option when you want the full dashboard rather than guessing a name.
When it happens
Trigger: Calling renderDashboard({ panel: 'summary' }) when 'summary' is not in VALID_PANELS (valid ones include e.g. 'amendments', 'versions'); passing a CLI --panel flag with a typo or different casing ('Health' vs 'health'); passing panel names from an older version that were renamed or removed.
Common situations: Users typing panel names from memory in CLI invocations; scripts generated against an older library version where panels were renamed; case-sensitive matching breaking on user input like 'Overview'.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- --host-provider must be anthropic, openai, or unknown
- Invalid --action value
- Invalid format: . Use text, json, or markdown.
- Invalid format: . Use text, json, or markdown.
- Invalid format: . Use text, json, or markdown.
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/5ee116c365f177e0.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/skill-evolution/dashboard.js:353
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(', ')}`);
}
const panels = {};
const textParts = [];
const header = [
'ECC Skill Health Dashboard',
`Generated: ${now}`,
`Skills: ${summary.total_skills} total, ${summary.healthy_skills} healthy, ${summary.declining_skills} declining`,
'',
];
textParts.push(header.join('\n'));
if (selectedPanel) {
const result = panelRenderers[selectedPanel]();
panels[selectedPanel] = result.data;
textParts.push(result.text);View on GitHub (pinned to 8321021c54)