stablyai/orca · error
${targetName} provider alias was replaced with an independen
Error message
${targetName} provider alias was replaced with an independent copy What it means
After a targeted 'skills update <targetName> --global' in symlink shape, the script lstat's the target provider placement and requires it to still be a symbolic link. If the update replaced the symlink with a real directory/copy, it throws — the topology must be preserved as an alias.
Source
Thrown at config/scripts/verify-skill-update-roundtrip.mjs:215
skillPath: `skills/${controlName}/SKILL.md`,
skillFolderHash: controlHistorical.snapshot.gitTreeSha,
installedAt: timestamp,
updatedAt: timestamp
}
}
}
const lockPath = path.join(stateHome, 'skills', '.skill-lock.json')
await mkdir(path.dirname(lockPath), { recursive: true })
await writeFile(lockPath, `${JSON.stringify(lock, null, 2)}\n`)
// Why: this is the exact user-visible rail. A bare update would include
// unrelated vendors, while this command must leave the control skill alone.
execSkills(['update', targetName, '--global'])
await assertCurrentCanonical(targetName)
const targetProviderAfter = await packageDigestAt(await realpath(targetProvider))
const targetProviderStat = await lstat(targetProvider)
if (shape === 'symlink' && !targetProviderStat.isSymbolicLink()) {
throw new Error(`${targetName} provider alias was replaced with an independent copy`)
}
if (shape === 'symlink' && targetProviderAfter !== currentSkill(targetName).packageDigest) {
throw new Error(`${targetName} provider alias did not converge with the canonical update`)
}
if (
shape === 'copy' &&
targetProviderAfter !== targetProviderBefore &&
targetProviderAfter !== currentSkill(targetName).packageDigest
) {
throw new Error('Independent provider copy changed to an unexpected package identity')
}
if (shape === 'copy') {
// Why: hosted 1.5.17 replaces copies with aliases while equivalent local runs
// retain the copy. Both prove this input topology must remain ineligible.
const outcome = targetProviderStat.isSymbolicLink()
? 'converged to an alias'
: targetProviderAfter === targetProviderBefore
? 'remained a historical copy'View on GitHub (pinned to 1136503c6a)
Solutions
- Before the update, assert the provider placement is a valid symlink (lstat.isSymbolicLink && realpath resolves).
- File a CLI bug: a targeted update in symlink topology must not replace the alias with an independent copy.
- If the symlink was dangling, recreate it correctly before re-running the round-trip.
- Pin to a CLI version known to preserve symlink topology until the regression is fixed.
Defensive patterns
Strategy: validation
Validate before calling
// Before the update, assert the provider placement is a healthy symlink:
import { lstatSync, realpathSync } from 'node:fs'
function assertHealthySymlink(p) {
const st = lstatSync(p)
if (!st.isSymbolicLink()) throw new Error(`${p} is not a symlink going into the update`)
realpathSync(p) // throws if dangling
}
assertHealthySymlink(targetProvider) Prevention
- Treat any topology change after a targeted update as a CLI regression; file it rather than weakening the assertion.
- On Windows, run only where symlink privilege is available when shape=symlink.
- Pin the CLI version under test; don't let 'latest' introduce a topology regression silently.
When it happens
Trigger: The CLI's update path, when fixing an out-of-date provider, deletes the symlink and writes an independent directory instead; a copy-fallback path triggers when it shouldn't for symlink shape; the provider symlink was already broken before the update and the update 'repaired' it as a copy.
Common situations: CLI regression that changes topology from alias to copy on update; pre-existing dangling symlink that the update normalizes; cross-platform path handling that turns a relative symlink into a resolved copy.
Related errors
- ${targetName} provider alias did not converge with the canon
- Targeted update changed the non-targeted control skill
- Targeted update changed the non-targeted control topology
- packaged plugin contains a symlink: ${relative(root, entryPa
- Usage: verify-skill-update-roundtrip.mjs --cli=<version> --a
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/c826d81f13097dad.
Report an issue: GitHub.