Skip to content

fix(installer): handle cleanup failures without panicking#2088

Merged
baszalmstra merged 2 commits intoconda:mainfrom
suhr25:pr-installer-only
Feb 22, 2026
Merged

fix(installer): handle cleanup failures without panicking#2088
baszalmstra merged 2 commits intoconda:mainfrom
suhr25:pr-installer-only

Conversation

@suhr25
Copy link
Copy Markdown
Contributor

@suhr25 suhr25 commented Feb 20, 2026

Summary

This PR improves robustness in the package installation pipeline by removing two instances where filesystem errors could cause unexpected process panics.

The first issue occurs in crates/rattler_cache/src/package_cache/mod.rs within the download retry loop. When a package fails its SHA-256 or MD5 hash validation, the code attempts to delete the partially extracted directory before retrying. This cleanup step previously used .unwrap(), meaning any transient OS-level failure (e.g., file locks, permission issues) would crash the process instead of allowing the retry logic to proceed.

The second issue is in crates/rattler/src/install/installer/mod.rs inside execute_transaction, the main function responsible for install, update, and removal operations. After unlinking packages, it calls remove_empty_directories(...) to clean up leftover directories. This also used .unwrap(), causing the entire transaction to panic on any cleanup failure rather than returning a structured error.

These scenarios are particularly common on Windows systems, where background processes like antivirus scanners or indexing services can temporarily lock files.

# fix(installer): propagate filesystem errors instead of panicking


---

## Fix

### 1. Hash mismatch cleanup (package_cache)

The temporary directory involved in extraction is already managed by a `TempDir` guard, ensuring cleanup on drop. The explicit deletion before retry is therefore an optimization, not a requirement.

Instead of panicking on failure, the code now logs a warning and continues:

```rust
if let Err(e) = tokio_fs::remove_dir_all(&destination).await {
    tracing::warn!(
        "failed to remove destination on sha256 mismatch \
         (will be cleaned up on drop): {e}"
    );
}

This preserves retry behavior while avoiding unnecessary crashes.


2. Empty directory cleanup (installer)

The installer already defines InstallerError::UnlinkError for filesystem-related failures. The fix replaces .unwrap() with proper error propagation:

driver
    .remove_empty_directories(&transaction.operations, transaction.unchanged_packages(), &prefix)
    .map_err(|e| InstallerError::UnlinkError("remove_empty_directories".to_string(), e))?;

This ensures cleanup failures are surfaced to the caller instead of causing a panic.


Verification

  • The retry loop in get_or_fetch_from_url_with_retry continues to behave as expected, returning ExtractError::HashMismatch and retrying appropriately.
  • execute_transaction now returns InstallerError::UnlinkError on cleanup failure, which is already handled by existing error flows.
  • The normal (successful) execution path remains unchanged.
  • On systems with transient file locks (e.g., Windows with antivirus scanning), installation no longer fails due to cleanup-related panics.

Notes

  • No new error types or APIs were introduced.
  • Changes are minimal and consistent with existing error-handling patterns in the codebase.
  • This PR aligns with the project’s reliability expectations for handling real-world filesystem behavior.

Replace .unwrap() on tokio_fs::remove_dir_all in the sha256 and md5
hash-mismatch cleanup paths with a non-fatal tracing::warn!. The temp
directory is already managed by a TempDir guard and will be removed on
drop; a cleanup failure should not panic the retry loop and crash the
installer.

Signed-off-by: suhr25 <suhridmarwah07@gmail.com>
…anicking

Replace .unwrap() on driver.remove_empty_directories() with
.map_err(|e| InstallerError::UnlinkError(...))? so any filesystem
error during empty-dir cleanup is returned as a structured
InstallerError rather than crashing the process.

Signed-off-by: suhr25 <suhridmarwah07@gmail.com>
@suhr25
Copy link
Copy Markdown
Contributor Author

suhr25 commented Feb 21, 2026

Hi @wolfv @baszalmstra
Fixed two .unwrap() usages that could panic on filesystem cleanup failures. Now we log and continue for retry cases, and properly propagate errors in the installer instead of crashing.

@baszalmstra baszalmstra merged commit d6e1a8b into conda:main Feb 22, 2026
18 checks passed
@github-actions github-actions Bot mentioned this pull request Feb 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants