affaan-m/ECC · error
Missing provenance metadata for ${skillDir}
Error message
Missing provenance metadata for ${skillDir} What it means
Thrown by readProvenance when the .provenance.json file does not exist AND provenance is required. Provenance is required when options.required === true OR requiresProvenance() classifies the skill dir as learned/imported (i.e. under ~/.claude/skills/learned or /imported). For curated/unknown paths with no file, readProvenance returns null instead.
Source
Thrown at scripts/lib/skill-evolution/provenance.js:147
errors,
};
}
function assertValidProvenance(record) {
const validation = validateProvenance(record);
if (!validation.valid) {
throw new Error(`Invalid provenance metadata: ${validation.errors.join('; ')}`);
}
}
function readProvenance(skillPath, options = {}) {
const skillDir = normalizeSkillDir(skillPath);
const provenancePath = getProvenancePath(skillDir);
const provenanceRequired = options.required === true || requiresProvenance(skillDir, options);
if (!fs.existsSync(provenancePath)) {
if (provenanceRequired) {
throw new Error(`Missing provenance metadata for ${skillDir}`);
}
return null;
}
const record = JSON.parse(fs.readFileSync(provenancePath, 'utf8'));
assertValidProvenance(record);
return record;
}
function writeProvenance(skillPath, record, options = {}) {
const skillDir = normalizeSkillDir(skillPath);
if (!requiresProvenance(skillDir, options)) {
throw new Error(`Provenance metadata is only required for learned or imported skills: ${skillDir}`);
}
assertValidProvenance(record);View on GitHub (pinned to 01e15490f0)
Solutions
- Create the metadata first with writeProvenance(dir, validRecord).
- If absence is acceptable, call readProvenance without options.required and handle a null return.
- Move the skill into a curated root (repo skills/) where provenance is optional, or fix repoRoot/homeDir so the path classifies correctly.
Example fix
// before
const p = readProvenance(learnedDir); // throws if no .provenance.json
// after
const p = readProvenance(learnedDir);
// or, if you just want a best-effort read:
const p = readProvenance(learnedDir, { required: false }); // null when absent
// or create it:
writeProvenance(learnedDir, { source, created_at, confidence, author }); Defensive patterns
Strategy: try-catch
Validate before calling
const { requiresProvenance } = require('./provenance');
function safeReadProvenance(dir, options = {}) {
if (!fs.existsSync(getProvenancePath(dir))) {
if (!options.required && !requiresProvenance(dir, options)) return null;
}
return readProvenance(dir, options);
} Type guard
function provenanceExists(skillPath) {
return fs.existsSync(path.join(skillPath, '.provenance.json'));
} Try / catch
try {
return readProvenance(dir);
} catch (err) {
if (/Missing provenance metadata/.test(err.message)) {
writeProvenance(dir, buildDefaultRecord());
return readProvenance(dir);
}
throw err;
} Prevention
- Call writeProvenance during skill import/learn so the file always exists.
- Use { required: false } for best-effort reads and handle null.
- Treat .provenance.json as part of the skill artifact when copying/moving dirs.
When it happens
Trigger: readProvenance('/home/u/.claude/skills/learned/foo') where foo has no .provenance.json; readProvenance(anyDir, { required: true }) with no file present.
Common situations: A learned/imported skill was created without provenance metadata; the skill directory was moved/copied without the .provenance.json; fresh import pipeline skipped the metadata step; options.required forced on a path that legitimately lacks it.
Related errors
- Missing value for --family
- skillPath is required
- Invalid provenance metadata: ${validation.errors.join('; ')}
- Provenance metadata is only required for learned or imported
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/756099127382e3ef.
Report an issue: GitHub.