farion1231/cc-switch · error · anyhow::Error
MCode Skill 与托管副本内容不同,拒绝替换链接
Error message
MCode Skill 与托管副本内容不同,拒绝替换链接: {dir_name} What it means
When syncing a skill into the MCode (MiniMax Code) app directory, the code finds the native destination is a symlink that does not alias the intended target. It then compares content hashes of the linked (managed) copy and the new source; if they differ, replacement is refused to avoid clobbering a symlink whose pointed-to content diverged from the deployed skill. This guards against replacing a link that no longer matches managed content.
Solutions
- Diff the content at the native symlink target against the new skill source; if the local edits are unwanted, delete the divergent content and re-run the sync so the link is replaced.
- If the local modifications are wanted, rename/backup the divergent directory, then re-run deployment to establish a fresh managed link.
- Verify the symlink actually points at the intended managed copy (paths_alias check) — a wrong symlink target is often the root cause.
- Re-import or re-hash the skill so its deployment hash matches, then retry.
Example fix
// before: sync fails because the linked copy was hand-edited
sync_skill_to_mcode(dir_name)?;
// after: back up the divergent copy and re-sync
fs::rename(&native, native.with_extension("bak"));
sync_skill_to_mcode(dir_name)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_replacable(native: &Path, dest: &Path) -> bool {
if !is_symlink(native) || paths_alias(native, dest) { return true; }
compute_pi_deployment_hash(native) == compute_pi_deployment_hash(dest)
} Try / catch
if let Err(e) = sync_skill_to_mcode(dir_name) {
if e.to_string().contains("拒绝替换链接") {
backup_and_remove_link(native)?;
sync_skill_to_mcode(dir_name)?;
} else { return Err(e); }
} Prevention
- Don't hand-edit files inside symlinked managed skill directories
- Verify symlink targets point at the SSOT before deploying
- Back up local modifications before re-running skill sync
- Keep deployment hashes in sync by re-importing after content changes
When it happens
Trigger: Deploying/importing a skill where the app's skills dir entry for dir_name is a symlink pointing somewhere other than the SSOT path, AND compute_pi_deployment_hash(native) != compute_pi_deployment_hash(dest) — i.e. the linked copy's files were modified after deployment so it no longer matches the incoming skill content.
Common situations: A user manually edited files inside the symlinked skill directory; the skill was previously linked to a different/custom skill source; an older deployment left a stale symlink after the SSOT content was updated; switching between managed and hand-crafted versions of the same skill name.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Pi 中已存在同名但内容不同的 Skill,拒绝覆盖或删除
- ; MiniMax Code Skill rollback failed: ; backups
- Imported Skills; skipped MiniMax Code entries
- Pi 中的 Skill 已在操作期间发生变化,拒绝覆盖
- Skill already exists, please uninstall the current one first
AI-assisted analysis of farion1231/cc-switch@06082e189d (2026-09-19).
Data as JSON: /api/errors/18741fd1b37a29fd.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/services/skill.rs:2162
// 解析元数据
let skill_md = dest.join("SKILL.md");
let (name, description) = Self::read_skill_name_desc(&skill_md, &dir_name);
// 其他应用保存用户选择;Pi 的 exists=active 必须直接来自原生目录。
let mut apps = selection.apps;
apps.pi = Self::skill_exists_in_app(&dir_name, &AppType::Pi);
// An explicitly imported MCode link must point at the managed copy
// so subsequent toggles and updates can verify its ownership.
if apps.mcode {
let projection = (|| -> Result<()> {
let native = Self::get_distinct_app_skills_dir(&ssot_dir, &AppType::Mcode)?
.join(&dir_name);
if Self::is_symlink(&native) && !Self::paths_alias(&native, &dest) {
if Self::compute_pi_deployment_hash(&native)?
!= Self::compute_pi_deployment_hash(&dest)?
{
return Err(anyhow!(
"MCode Skill 与托管副本内容不同,拒绝替换链接: {dir_name}"
));
}
if let Some(deployment) =
Self::inspect_pi_skill_destination(&native, &native, &dir_name)?
{
Self::refresh_pi_skill_destination(
&dest,
&native,
&dir_name,
&deployment,
)?;
}
} else {
Self::preflight_install_destination(&dest, &dir_name, &AppType::Mcode)?;
}
if !native.exists() {
Self::sync_to_app_dir(&dir_name, &AppType::Mcode)?;View on GitHub (pinned to 06082e189d)