affaan-m/ECC · error

Version not found: v${normalizedTargetVersion}

Error message

Version not found: v${normalizedTargetVersion}

What it means

Thrown by rollbackTo() after the target version passes the integer check but the corresponding snapshot file (vN.md inside the skill's .versions directory) does not exist on disk. This means versioning was never initialized for that version, or the snapshot was deleted. The function refuses to overwrite the current SKILL.md with nothing.

Source

Thrown at scripts/lib/skill-evolution/versioning.js:196

  return {
    version: nextVersion,
    path: snapshotPath,
    created_at: createdAt,
  };
}

function rollbackTo(skillPath, targetVersion, options = {}) {
  const normalizedTargetVersion = Number(targetVersion);
  if (!Number.isInteger(normalizedTargetVersion) || normalizedTargetVersion <= 0) {
    throw new Error(`Invalid target version: ${targetVersion}`);
  }

  ensureSkillExists(skillPath);
  ensureSkillVersioning(skillPath);

  const targetPath = path.join(getVersionsDir(skillPath), `v${normalizedTargetVersion}.md`);
  if (!fs.existsSync(targetPath)) {
    throw new Error(`Version not found: v${normalizedTargetVersion}`);
  }

  const currentVersion = getCurrentVersion(skillPath);
  const targetContent = fs.readFileSync(targetPath, 'utf8');
  fs.writeFileSync(getSkillFilePath(skillPath), targetContent, 'utf8');

  const createdVersion = createVersion(skillPath, {
    timestamp: options.timestamp,
    reason: options.reason || `rollback to v${normalizedTargetVersion}`,
    author: options.author || null,
  });

  appendEvolutionRecord(skillPath, 'amendments', {
    event: 'rollback',
    version: createdVersion.version,
    source_version: currentVersion,
    target_version: normalizedTargetVersion,
    reason: options.reason || null,

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Call listVersions(skillPath) first and pick a target whose .version field actually appears in the result.
  2. If no versions exist, call createVersion(skillPath, {...}) to capture the current state as v1, then retry.
  3. Make sure the skill's .versions directory is committed to source control or otherwise preserved across clones if you need rollback to work in CI.
  4. Confirm you are not off-by-one: versions are 1-indexed and capped at the highest existing snapshot.

Example fix

// before
rollbackTo(skillPath, 5);  // only v1..v3 exist -> Version not found: v5

// after
const versions = listVersions(skillPath);
const target = versions.find(v => v.version === desiredVersion);
if (!target) throw new Error(`no snapshot for v${desiredVersion}`);
rollbackTo(skillPath, target.version);
Defensive patterns

Strategy: validation

Validate before calling

const { listVersions, rollbackTo } = require('scripts/lib/skill-evolution/versioning');

function rollbackToExisting(skillPath, desired) {
  const versions = listVersions(skillPath).map(v => v.version);
  if (!versions.includes(desired)) {
    throw new Error(`Version ${desired} not available; choices: ${versions.join(', ')}`);
  }
  return rollbackTo(skillPath, desired);
}

Type guard

const { listVersions } = require('scripts/lib/skill-evolution/versioning');

function versionExists(skillPath, target) {
  return listVersions(skillPath).some(v => v.version === target);
}

Try / catch

try {
  rollbackTo(skillPath, target);
} catch (error) {
  if (/Version not found/.test(error.message)) {
    const latest = getCurrentVersion(skillPath);
    if (latest > 0) rollbackTo(skillPath, latest);
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling rollbackTo(skillPath, 5) when only v1.md, v2.md, v3.md exist; calling rollback before createVersion has run even once; rolling back to a version that was pruned manually; the .versions directory was gitignored and lost on a fresh clone.

Common situations: Asking for a version larger than getCurrentVersion() returns; fresh checkout that did not preserve .versions; an external cleanup tool removed old snapshots; the caller computed the target from a stale list.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/5b4719e62b6704e4. Report an issue: GitHub.