ReactiveX/rxjs · error · Error
Refusing to overwrite a locally modified Skill copy at ${ins
Error message
Refusing to overwrite a locally modified Skill copy at ${installation.targetPath} without explicit force. What it means
Thrown by updateSkill when the existing skill copy is state 'modified' (its digest no longer matches canonical) and --force is absent. The update would destroy local edits, so the CLI requires explicit consent.
Source
Thrown at packages/migrate/src/skill-install.ts:132
}
export async function installSkill(options: SkillInstallOptions): Promise<SkillInstallResult> {
const installation = await resolveInstallation(options);
const state = await installationState(installation);
if (state === 'current') return resultFor('install', installation, state, state, false);
if (state !== 'absent' && !options.force) {
throw new Error(`Refusing to install over a ${state} Skill copy at ${installation.targetPath}. Use update or explicit force.`);
}
await replaceInstallation(installation);
return resultFor('install', installation, state, 'current', true);
}
export async function updateSkill(options: SkillInstallOptions): Promise<SkillInstallResult> {
const installation = await resolveInstallation(options);
const state = await installationState(installation);
if (state === 'current') return resultFor('update', installation, state, state, false);
if (state === 'modified' && !options.force) {
throw new Error(`Refusing to overwrite a locally modified Skill copy at ${installation.targetPath} without explicit force.`);
}
await replaceInstallation(installation);
return resultFor('update', installation, state, 'current', true);
}
export async function removeSkill(options: SkillInstallOptions): Promise<SkillInstallResult> {
const installation = await resolveInstallation(options);
const state = await installationState(installation);
if (state === 'absent') return resultFor('remove', installation, state, state, false);
if (state === 'modified' && !options.force) {
throw new Error(`Refusing to remove a locally modified Skill copy at ${installation.targetPath} without explicit force.`);
}
await rm(installation.targetPath, { recursive: true, force: false });
return resultFor('remove', installation, state, 'absent', true);
}
export function manageSkillInstallation(action: SkillInstallAction, options: SkillInstallOptions): Promise<SkillInstallResult> {
switch (action) {View on GitHub (pinned to 54796b38a5)
Solutions
- Back up your local edits, rerun with --force, then re-apply the edits
- Keep customizations outside the managed skill directory and re-integrate after update
- If edits are unwanted, just use --force directly
Example fix
# before rxjs-migrate-skill update --harness claude # after cp -r .claude/skills/rxjs-migrate /tmp/skill-backup rxjs-migrate-skill update --harness claude --force
Defensive patterns
Strategy: try-catch
Validate before calling
const modified = await detectModifiedSkillCopy(targetPath); // compare digest vs canonical before updating
Try / catch
try { updateSkill(opts); } catch (e) { if (e instanceof Error && e.message.includes('locally modified')) { /* back up, then retry with force: true */ } throw e; } Prevention
- Keep customizations outside managed skill directories
- Back up before update --force
When it happens
Trigger: Running rxjs-migrate-skill update after hand-editing the installed SKILL.md or harness files, without --force.
Common situations: Teams customizing the installed skill then upgrading @rxjs/migrate; the update would revert their changes.
Related errors
- Refusing to install over a ${state} Skill copy at ${installa
- Refusing to remove a locally modified Skill copy at ${instal
- Invalid Skill installation provenance.
- Unknown mode: ${mode}
- Unknown framework: ${framework}
AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28).
Data as JSON: /api/errors/b25b801500376f1f.
Report an issue: GitHub.