affaan-m/ECC · error
skillPath is required
Error message
skillPath is required
What it means
Thrown by normalizeSkillDir in the versioning module (reached via getSkillFilePath and the version/amendment log writers) when skillPath is falsy or not a string. Identical contract to provenance.normalizeSkillDir: accepts a directory or a path ending in SKILL.md.
Source
Thrown at scripts/lib/skill-evolution/versioning.js:18
'use strict';
const fs = require('fs');
const path = require('path');
const { appendFile, ensureDir } = require('../utils');
const VERSION_DIRECTORY_NAME = '.versions';
const EVOLUTION_DIRECTORY_NAME = '.evolution';
const EVOLUTION_LOG_TYPES = Object.freeze([
'observations',
'inspections',
'amendments',
]);
function normalizeSkillDir(skillPath) {
if (!skillPath || typeof skillPath !== 'string') {
throw new Error('skillPath is required');
}
const resolvedPath = path.resolve(skillPath);
if (path.basename(resolvedPath) === 'SKILL.md') {
return path.dirname(resolvedPath);
}
return resolvedPath;
}
function getSkillFilePath(skillPath) {
return path.join(normalizeSkillDir(skillPath), 'SKILL.md');
}
function ensureSkillExists(skillPath) {
const skillFilePath = getSkillFilePath(skillPath);
if (!fs.existsSync(skillFilePath)) {
throw new Error(`Skill file not found: ${skillFilePath}`);View on GitHub (pinned to 01e15490f0)
Solutions
- Pass the skill directory path (or the SKILL.md file path) as a non-empty string.
- Guard callers for undefined before invoking.
- Resolve the path once upstream and reuse it.
Example fix
// before versioning.getSkillFilePath(skill?.dir); // after if (skill?.dir) versioning.getSkillFilePath(skill.dir);
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof skillPath !== 'string' || skillPath.trim().length === 0) {
throw new TypeError('skillPath must be a non-empty string');
}
versioning.getSkillFilePath(skillPath); Type guard
function isNonEmptyString(v) {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
versioning.getSkillFilePath(skillPath);
} catch (err) {
if (/skillPath is required/.test(err.message)) return null;
throw err;
} Prevention
- Resolve the skill directory once and pass it as a string to all versioning calls.
- Never substitute the skill record/config object for its path.
- Wrap versioning APIs in a shared helper that type-checks the path.
When it happens
Trigger: Calling versioning.getSkillFilePath(undefined); versioning.appendObservation(null, ...); passing a skill config object instead of its path.
Common situations: Undefined loop/destructure variable; calling versioning APIs before resolving the skill directory; passing the SKILL.md contents instead of the path.
Related errors
- --config-dir must be an existing absolute directory.
- ${EXECUTABLE_OVERRIDE} must be an absolute path explicitly c
- ${EXECUTABLE_OVERRIDE} does not point to a readable local It
- ${EXECUTABLE_OVERRIDE} must point to the canonical dist/bin/
- Invalid ${name} value: expected a path
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/ab988770e7b61d99.
Report an issue: GitHub.