{"record":{"id":"c319bfea099d3712","repo":"libnyanpasu/clash-nyanpasu","slug":"ready-symlink-path-is-occupied-by-an-unexpected-no","errorCode":null,"errorMessage":"ready symlink path is occupied by an unexpected node","messagePattern":"ready symlink path is occupied by an unexpected node","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/service/profile_file.rs","lineNumber":886,"sourceCode":"                target: ExternalProfilePath::new(target)?,\n            }));\n        }\n        Ok(None)\n    }\n\n    fn create_ready_link(\n        root: &Path,\n        operation_id: &str,\n        target: &ExternalProfilePath,\n    ) -> anyhow::Result<PathBuf> {\n        let ready = Self::ready_link_path(root, operation_id);\n        match std::fs::symlink_metadata(&ready) {\n            Ok(metadata) if metadata.file_type().is_symlink() => {\n                if std::fs::read_link(&ready)? != target.as_path() {\n                    bail!(\"ready symlink target mismatch\");\n                }\n            }\n            Ok(_) => bail!(\"ready symlink path is occupied by an unexpected node\"),\n            Err(error) if error.kind() == std::io::ErrorKind::NotFound => {\n                create_file_symlink(target.as_path(), &ready)\n                    .with_context(|| format!(\"create staged symlink {}\", ready.display()))?;\n                sync_directory(ready.parent().expect(\"ready symlink has parent\"))?;\n            }\n            Err(error) => return Err(error).context(\"inspect ready symlink\"),\n        }\n        Ok(ready)\n    }\n\n    fn promote_resource(\n        &self,\n        root: &Path,\n        operation_id: &str,\n        target: &Path,\n        expected_hash: &str,\n    ) -> anyhow::Result<()> {\n        self.ensure_managed_parent(target)?;","sourceCodeStart":868,"sourceCodeEnd":904,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/service/profile_file.rs#L868-L904","documentation":"create_ready_link found a node at the ready symlink path that is not a symlink (regular file, directory, etc.). The staging protocol requires that path to be either a correct symlink or absent; anything else indicates corruption or external interference, so the operation aborts.","triggerScenarios":"A ready symlink path is occupied by a non-symlink node: a regular file or directory was created at ready_link_path(root, operation_id), e.g. by a crash leftover, another tool, or a filesystem that materialized the link as a file.","commonSituations":"Manual cleanup replaced the symlink with a copy; sync/backup tools dereferenced symlinks into regular files; non-symlink-supporting filesystems (some Windows configs/network mounts) writing plain files.","solutions":["Remove the foreign node at the ready path (after confirming it is not user data) and rerun the materialization.","Run the journal compensate/reconcile flow to reset the operation's staged state.","Check the filesystem supports symlinks (Windows developer mode / not a FAT or network share) if this recurs.","Verify no other process or backup tool is writing into the staging directory."],"exampleFix":"// before\n// ready path holds a regular file left by a backup tool\n// after\nstd::fs::remove_file(&ready_path)?; // after verifying contents\nclient.promote(root, operation_id).await?;","handlingStrategy":"try-catch","validationCode":"if let Ok(meta) = std::fs::symlink_metadata(&ready_path) {\n    if !meta.file_type().is_symlink() {\n        // occupied by a non-symlink node: clean up before calling\n        std::fs::remove_file(&ready_path)?;\n    }\n}","typeGuard":"fn is_symlink_node(p: &Path) -> bool {\n    std::fs::symlink_metadata(p).map(|m| m.file_type().is_symlink()).unwrap_or(false)\n}","tryCatchPattern":"match create_ready_link(root, &target) {\n    Err(e) if e.to_string().contains(\"unexpected node\") => {\n        let _ = std::fs::remove_file(Self::ready_link_path(root, &op_id));\n        create_ready_link(root, &target)\n    }\n    r => r,\n}","preventionTips":["Exclude the staging root from backup/sync tools that dereference symlinks.","Use a filesystem that supports symlinks (enable Windows symlink privileges).","Keep staging directories user-private to avoid foreign writes.","Run reconcile periodically to clear corrupted staging nodes."],"tags":["filesystem","symlink","corruption"],"backgroundTag":"invalid-state-transition","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}