libnyanpasu/clash-nyanpasu · error

cleanup journal destination is not a regular file: {}

Error message

cleanup journal destination is not a regular file: {}

What it means

Same guard as the materialization transition, but for the cleanup journal family: transition_cleanup_journal moves a cleanup journal between CleanupPhase locations (e.g. Pending -> Ready). If the destination cleanup-journal path exists as a symlink/reparse point or a non-regular file, the library refuses rather than writing through it. This protects the cleanup recovery path from foreign or hostile artifacts.

Source

Thrown at backend/tauri/src/service/profile_file.rs:1259

            }
            Err(error) => Err(error).context("inspect journal destination"),
        }
    }

    fn transition_cleanup_journal(
        root: &Path,
        operation_id: &str,
        from: CleanupPhase,
        to: CleanupPhase,
    ) -> anyhow::Result<()> {
        let source = Self::cleanup_path(root, from, operation_id);
        let destination = Self::cleanup_path(root, to, operation_id);
        let source_journal = Self::read_journal(&source, operation_id)?;
        match std::fs::symlink_metadata(&destination) {
            Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
                Self::advance_journal_phase(&source, &destination, &source_journal)
            }
            Ok(metadata) if is_symlink_or_reparse(&metadata) || !metadata.is_file() => bail!(
                "cleanup journal destination is not a regular file: {}",
                destination.display()
            ),
            Ok(_) => {
                if Self::read_journal(&destination, operation_id)? != source_journal {
                    bail!("cleanup journal destination has a different payload");
                }
                Self::remove_private_regular(&source)
            }
            Err(error) => Err(error).context("inspect cleanup journal destination"),
        }
    }

    fn discard_materialization(
        root: &Path,
        operation_id: &str,
        location: JournalLocation,
    ) -> anyhow::Result<()> {

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Remove the symlink/non-file artifact at the reported destination path and retry the cleanup.
  2. Exclude the profiles private journal directory from cloud sync and antivirus real-time scanning.
  3. Abandon the cleanup by deleting all cleanup journals for that operation_id, then re-plan the cleanup.
  4. On Windows, confirm the path is not under a OneDrive 'files on demand' folder; download contents locally.

Example fix

// before: transition fails repeatedly
transition_cleanup_journal(root, &id, CleanupPhase::Pending, CleanupPhase::Ready)?;
// after: clear the non-file destination first
let dest = cleanup_path(root, CleanupPhase::Ready, &id);
let meta = std::fs::symlink_metadata(&dest)?;
if meta.is_symlink() || !meta.is_file() {
    std::fs::remove_file(&dest)?;
}
transition_cleanup_journal(root, &id, CleanupPhase::Pending, CleanupPhase::Ready)?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn cleanup_destination_ok(root: &Path, to: CleanupPhase, id: &str) -> bool {
    match std::fs::symlink_metadata(cleanup_path(root, to, id)) {
        Err(e) => e.kind() == std::io::ErrorKind::NotFound,
        Ok(m) => !m.is_symlink() && m.is_file(),
    }
}

Type guard

fn is_plain_file(m: &std::fs::Metadata) -> bool {
    !m.is_symlink() && m.is_file()
}

Try / catch

match transition_cleanup_journal(root, id, from, to) {
    Err(e) if e.to_string().contains("cleanup journal destination is not a regular file") => {
        // remove the foreign artifact at the printed path, retry once
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running profile cleanup recovery (transitioning the cleanup journal from Pending to Ready) when cleanup_path(root, to, operation_id) exists as a symlink, directory, or Windows reparse point — e.g. a sync client replaced the file or someone probed the cleanup directory manually.

Common situations: Cloud-drive placeholder reparse points on Windows intercepting the cleanup journal path; leftover test scaffolding that created a directory at the cleanup phase path; antivirus quarantining the journal and leaving a stub.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/4a8a5c00a3d5a589. Report an issue: GitHub.