affaan-m/ECC · error · Error
skill_version is required
Error message
skill_version is required
What it means
normalizeExecutionRecord() requires a skill_version string on every execution record, read from input.skill_version or input.skillVersion. Missing, non-string, or empty/whitespace-only values throw 'skill_version is required'. Version is mandatory so executions can be attributed to the exact skill iteration when evaluating skill evolution.
Solutions
- Include a non-empty skill_version string: record({ skill_id, skill_version: '1.0.0', ... }).
- Read the version from the skill's metadata/frontmatter and pass it explicitly; add a version to skills missing one.
- If your field is named 'version' or 'v', map it to skill_version (or skillVersion) before calling.
- Default to a known constant (e.g. '0.0.0' or from package.json) only if unversioned skills are acceptable in your analytics.
Example fix
// before
record({ skill_id: 'lint-repo', task_description: 'lint repo', outcome: 'success' });
// after
record({ skill_id: 'lint-repo', skill_version: skill.metadata.version ?? '0.0.0', task_description: 'lint repo', outcome: 'success' }); Defensive patterns
Strategy: validation
Validate before calling
function assertSkillVersion(payload) {
const v = payload?.skill_version ?? payload?.skillVersion;
if (typeof v !== 'string' || v.trim().length === 0) {
throw new TypeError('execution payload missing non-empty skill_version');
}
return v.trim();
} Type guard
function hasSkillVersion(input) {
const v = input?.skill_version ?? input?.skillVersion;
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
tracker.record(payload);
} catch (err) {
if (err.message === 'skill_version is required') {
console.error('Execution payload missing skill_version; read it from skill metadata before recording');
return;
}
throw err;
} Prevention
- Always read skill_version from the skill's frontmatter/metadata when building payloads.
- Require a version field in skill authoring templates so it is never absent.
- Apply a safe default (e.g. '0.0.0') in your recording adapter for unversioned skills.
When it happens
Trigger: record({ skill_id: 'lint-repo', task_description: 'x', outcome: 'success' }) with no version key; skill_version: '' after a trim; skill_version read from a skill manifest that lacks a version field and therefore came through as undefined.
Common situations: Skills authored without a version in frontmatter/metadata so callers have nothing to pass; pipelines where the version key was renamed (e.g. 'v' or 'version'); forgetting to bump/pass the version after a skill update; both snake_case and camelCase keys absent in a hand-built payload.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- skill_id is required
- task_description is required
- a confirmed nonempty coordinate is required
- must be a number
- outcome must be one of success, failure, or partial
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/939cb20618ccaa61.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/skill-evolution/tracker.js:62
function normalizeExecutionRecord(input, options = {}) {
if (!input || typeof input !== 'object' || Array.isArray(input)) {
throw new Error('skill execution payload must be an object');
}
const skillId = input.skill_id || input.skillId;
const skillVersion = input.skill_version || input.skillVersion;
const taskDescription = input.task_description || input.task_attempted || input.taskAttempted;
const outcome = input.outcome;
const recordedAt = input.recorded_at || options.now || new Date().toISOString();
const userFeedback = input.user_feedback || input.userFeedback || null;
if (typeof skillId !== 'string' || skillId.trim().length === 0) {
throw new Error('skill_id is required');
}
if (typeof skillVersion !== 'string' || skillVersion.trim().length === 0) {
throw new Error('skill_version is required');
}
if (typeof taskDescription !== 'string' || taskDescription.trim().length === 0) {
throw new Error('task_description is required');
}
if (!VALID_OUTCOMES.has(outcome)) {
throw new Error('outcome must be one of success, failure, or partial');
}
if (userFeedback !== null && !VALID_FEEDBACK.has(userFeedback)) {
throw new Error('user_feedback must be accepted, corrected, rejected, or null');
}
if (Number.isNaN(Date.parse(recordedAt))) {
throw new Error('recorded_at must be an ISO timestamp');
}
View on GitHub (pinned to 8321021c54)