Skip to content

fix: hint users to enable Developer Mode on Windows symlink extraction failure#2454

Open
pb01ka wants to merge 12 commits into
prefix-dev:mainfrom
pb01ka:win-symlink
Open

fix: hint users to enable Developer Mode on Windows symlink extraction failure#2454
pb01ka wants to merge 12 commits into
prefix-dev:mainfrom
pb01ka:win-symlink

Conversation

@pb01ka
Copy link
Copy Markdown

@pb01ka pb01ka commented Apr 28, 2026

Problem

Refer - #940 (comment)

When rattler-build tries to extract a source archive (e.g. a .tar.gz) that contains symbolic links on Windows without Developer Mode enabled, the extraction fails with an error such as (with no hint or actionable information):

 ╭─ Running build for recipe: podman-desktop-1.26.2-hf0b5a29_0
 │
 │ ╭─ Fetching source code
 │ │ Fetching source from url: https://github.com/podman-desktop/podman-desktop/archive/refs/tags/v1.26.2.tar.gz
 │ │ Downloading from: https://github.com/podman-desktop/podman-desktop/archive/refs/tags/v1.26.2.tar.gz
 │ │ ⚠ warning Failed to fetch from https://github.com/podman-desktop/podman-desktop/archive/refs/tags/v1.26.2.tar.gz: Failed to extract archive: Failed to extract tar
 │ │ ⚠ warning .gz: failed to unpack `\\?\C:\Users\Gagan\staged-recipes\build_artifacts\src_cache\.tmpyweool\podman-desktop-1.26.2\CLAUDE.md`
 │ │
 │ ╰─────────────────── (took 8 seconds)
 │
 ╰─────────────────── (took 8 seconds)
Error:   x Failed to extract archive: Failed to extract tar.gz: failed to unpack `\\?\C:\Users\Gagan\staged-recipes\build_artifacts\src_cache\.tmpyweool\podman-desktop-
  | 1.26.2\CLAUDE.md`

Solution

This PR detects the failure scenario and surfaces an actionable hint:

  1. Registry check - a new is_windows_developer_mode_enabled() function checks whether Developer Mode is enabled by reading the registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlockAllowDevelopmentWithoutDevLicense using the winreg crate. This is safe Rust with no unsafe blocks.

  2. Improved error message - a new tar_unpack_error() helper wraps every tar .unpack() failure. On Windows, when Developer Mode is detected as disabled, the error is extended with a clear hint:

    hint: Extracting this archive failed on Windows. The archive may contain symbolic
    links, which require Developer Mode or administrator privileges to create.
    Please enable Developer Mode in:
    Developer settings > Developer Mode, then retry the build.
    
  3. Test coverage - a Windows-only unit test (test_symlink_extraction_error_message) builds a minimal .tar.gz containing a symlink entry and asserts that:

    • with Developer Mode off: the error message contains "Developer Mode".
    • with Developer Mode on: extraction succeeds without error.

Notes

  • No behaviour change on Linux/macOS — tar_unpack_error compiles to a simple CacheError::ExtractionError wrapper on non-Windows targets.
  • The winreg crate is added as a new Windows-only dependency; it provides safe, idiomatic Rust access to the Windows registry with no unsafe code.

This is my first contribution to rattler-build. I've done my best to follow the project's conventions, but I'm very much looking forward to feedback and suggestions for improvement - please feel free to point out anything that could be done better!

pb01ka added 5 commits April 28, 2026 15:54
…raction failure

When extracting a tar archive on Windows fails (e.g. due to symlinks
requiring elevated privileges), check whether Developer Mode is enabled via the registry. If it is not, append an actionable hint pointing the user to Settings > System > For developers > Developer Mode.
@pb01ka pb01ka changed the title Hint users to enable Developer Mode on Windows symlink extraction failure fix: hint users to enable Developer Mode on Windows symlink extraction failure Apr 28, 2026
@pb01ka pb01ka marked this pull request as draft April 28, 2026 20:04
@pb01ka pb01ka marked this pull request as ready for review April 28, 2026 20:29
@pb01ka pb01ka marked this pull request as draft April 29, 2026 10:47
@pb01ka pb01ka marked this pull request as ready for review April 29, 2026 13:33

/// Wraps a tar unpack error, appending a Windows Developer Mode hint when on Windows and
/// Developer Mode is detected as disabled.
fn tar_unpack_error(context: &str, e: std::io::Error) -> CacheError {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is also a specific io error that we are looking for? Permission denied or something?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not reliably. The error code when symlink creation fails on Windows with Developer Mode disabled is not consistent. ERROR_PRIVILEGE_NOT_HELD (1314) is the most common (as per my observation), but it can't reliably help in identifying a "symlink failed" error from the error alone, we instead gate the hint on the Developer Mode registry check: if Developer Mode is off and tar extraction fails for any reason, we surface the hint. The hint copy uses "may contain symbolic links" to reflect this uncertainty.

@baszalmstra
Copy link
Copy Markdown
Contributor

Having a clear error is nice, but maybe even just continuing would be even nicer.

In rattler/pixi we try to unpack symlinks, and if they fail, we simply ignore them and issue a warning. I think that behavior would also be fine here. If it's a problem that they are missing, you will find out soon enough during the build itself.

Another option that we could pursue instead is to create a symlink, and if that fails, we simply materialize/create a copy of the file.

@pb01ka
Copy link
Copy Markdown
Author

pb01ka commented May 8, 2026

@baszalmstra I think both alternatives are better UX than a hard failure.

  1. Warn and skip

In rattler/pixi we try to unpack symlinks, and if they fail, we simply ignore them and issue a warning. I think that behavior would also be fine here. If it's a problem that they are missing, you will find out soon enough during the build itself.

It is simpler to implement - the tar crate surfaces individual entry errors, so we could iterate entries manually instead of calling unpack(), and skip symlink entries that fail. The downside is the extracted tree is incomplete, which may cause silent build failures later.

  1. Fall back to copying the target file

Another option that we could pursue instead is to create a symlink, and if that fails, we simply materialize/create a copy of the file.

This approach is more robust - if the symlink target exists in the archive, we can materialise it as a regular file. The extracted tree is functionally complete even without actual symlinks.

I'd lean towards the copy fallback since it's transparent to the build, but it does require iterating tar entries manually and tracking regular files as they're extracted so we can copy them when a symlink to them is encountered. Happy to implement whichever approach you prefer.

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