← Back to issue list

Remote build fails on dangling symlinks

View original Github issue

Metadata

Project
craft-application
Number
#1103
Type
issue
State
closed
Author
bepri
Labels
—
Created
Updated
Closed

Current evaluation

remote-build crashed with shutil.Error on dangling symlinks because worktree copytree used default symlinks=False. Fixed by merged PR #1104 (commit 8256b7a2), which passes ignore_dangling_symlinks=True to copytree; released in 7.1.1.

Resolution: closed resolved

Reason: Merged PR #1104 ('fix(remote-build): ignore dangling symlinks'), commit 8256b7a2, changed craft_application/remote/worktree.py init_repo() to call copytree(self._project_dir, self._repo_dir, ignore_dangling_symlinks=True), so broken symlinks are skipped instead of raising shutil.Error.

Evaluated by: mr-cal-bot

No scores available.

Issue body

### Bug Description Attempting to use `remote-build` while in a directory that has dangling symlinks fails. This failure mode should not be forced by the craft tool, but rather should become a failure by the consuming build tools that the craft tool invokes (if it even _is_ an error). ### To Reproduce Create a broken symlink in any project, commit it, and then attempt to run `remote-build`. For example, ``` ├── here -> to-here # `to-here` doesn't exist! └── snap └── snapcraft.yaml ``` ### part yaml ```shell Irrelevant ``` ### Relevant log output ```shell 2026-06-25 11:18:42.312 Starting snapcraft, version 9.0.0 2026-06-25 11:18:42.312 Log verbosity level set to BRIEF 2026-06-25 11:18:42.312 Setting up Project 2026-06-25 11:18:42.312 Project file found at '/home/imani/work/scratch/snap/snapcraft.yaml' 2026-06-25 11:18:42.312 Loading project file 'snap/snapcraft.yaml 2026-06-25 11:18:42.313 Setting up BuildPlan 2026-06-25 11:18:42.313 Build plan contains 1 build(s). 2026-06-25 11:18:42.315 Loading app plugin sdplug 2026-06-25 11:18:42.338 Forward environment variables 2026-06-25 11:18:42.338 Registering craft-sd source handlers 2026-06-25 11:18:42.338 Registering craft-sd services 2026-06-25 11:18:42.338 SD not enabled. Skipping adding commands 2026-06-25 11:18:42.338 Request craft-sd snap installation in managed instance 2026-06-25 11:18:42.338 Skipping store secrets callback registration: SD not enabled. 2026-06-25 11:18:42.338 Preparing application... 2026-06-25 11:18:42.338 Setting up ConfigService 2026-06-25 11:18:42.342 Merging commands for group 'Lifecycle': 2026-06-25 11:18:42.342 - using application command for 'clean'. 2026-06-25 11:18:42.342 - using application command for 'pull'. 2026-06-25 11:18:42.342 - using application command for 'build'. 2026-06-25 11:18:42.342 - using application command for 'stage'. 2026-06-25 11:18:42.342 - using application command for 'prime'. 2026-06-25 11:18:42.342 - using application command for 'pack'. 2026-06-25 11:18:42.342 Merging commands for group 'Other': 2026-06-25 11:18:42.342 Configuring application... 2026-06-25 11:18:42.346 Build plan: platform=None, build_for=None 2026-06-25 11:18:42.346 Running snapcraft remote-build on host 2026-06-25 11:18:42.346 remote-build is experimental and is subject to change. Use with caution. 2026-06-25 11:18:42.346 Setting up RequestService 2026-06-25 11:18:42.346 Logging in with credentials file /home/imani/.local/share/snapcraft/launchpad-credentials. 2026-06-25 11:18:42.346 Emitter: Pausing control of the terminal 2026-06-25 11:18:47.629 Emitter: Resuming control of the terminal 2026-06-25 11:18:47.629 Trying to get project scratch (attempt 1/6) 2026-06-25 11:18:47.936 Emitter: Pausing control of the terminal 2026-06-25 11:18:48.750 Emitter: Resuming control of the terminal 2026-06-25 11:18:48.750 Build plan contains 1 build(s). 2026-06-25 11:18:48.750 Using '--build-for' as the list of architectures to build for 2026-06-25 11:18:48.750 Architectures to build for: 'amd64' 2026-06-25 11:18:48.750 Created project variables {'version': {'value': '0.1', 'updated': False, 'part-name': None}, 'grade': {'value': 'devel', 'updated': False, 'part-name': None}}. 2026-06-25 11:18:48.751 Using parallel build count of 16 from CPU count 2026-06-25 11:18:48.751 Checking if 'version' exists. 2026-06-25 11:18:48.751 Getting value for 'version'. 2026-06-25 11:18:48.751 Got '0.1' (updated=False) for 'version'. 2026-06-25 11:18:48.751 'version' exists. 2026-06-25 11:18:48.751 Getting value for 'version'. 2026-06-25 11:18:48.751 Got '0.1' (updated=False) for 'version'. 2026-06-25 11:18:48.751 Checking if 'version' exists. 2026-06-25 11:18:48.751 Getting value for 'version'. 2026-06-25 11:18:48.751 Got '0.1' (updated=False) for 'version'. 2026-06-25 11:18:48.751 'version' exists. 2026-06-25 11:18:48.751 Getting value for 'version'. 2026-06-25 11:18:48.751 Got '0.1' (updated=False) for 'version'. 2026-06-25 11:18:48.751 Checking if 'grade' exists. 2026-06-25 11:18:48.751 Getting value for 'grade'. 2026-06-25 11:18:48.751 Got 'devel' (updated=False) for 'grade'. 2026-06-25 11:18:48.751 'grade' exists. 2026-06-25 11:18:48.751 Getting value for 'grade'. 2026-06-25 11:18:48.751 Got 'devel' (updated=False) for 'grade'. 2026-06-25 11:18:48.751 Processing grammar (on amd64 for amd64) 2026-06-25 11:18:48.751 Processing grammar for plugin: nil 2026-06-25 11:18:48.757 Starting new build. It may take a while to upload large projects. 2026-06-25 11:18:48.759 snapcraft internal error: Error([('/home/imani/work/scratch/here', '/home/imani/.cache/snapcraft/remote-build/snapcraft-scratch-a22566aae87cb46312173f84fc845a49/repo/here', "[Errno 2] No such file or directory: '/home/imani/work/scratch/here'")]) 2026-06-25 11:18:48.771 Traceback (most recent call last): 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/application.py", line 693, in run 2026-06-25 11:18:48.771 return_code = self._run_inner() 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/snapcraft/application.py", line 180, in _run_inner 2026-06-25 11:18:48.771 return_code = super()._run_inner() 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/application.py", line 670, in _run_inner 2026-06-25 11:18:48.771 return_code = dispatcher.run() or os.EX_OK 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_cli/dispatcher.py", line 576, in run 2026-06-25 11:18:48.771 return self._loaded_command.run(self._parsed_command_args) 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/commands/base.py", line 222, in run 2026-06-25 11:18:48.771 result = self._run(parsed_args, **kwargs) or result 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/commands/remote.py", line 162, in _run 2026-06-25 11:18:48.771 builds = builder.start_builds(project_dir, **build_args) 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/services/remotebuild.py", line 133, in start_builds 2026-06-25 11:18:48.771 _, self._repository = self._ensure_repository(project_dir) 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/services/remotebuild.py", line 278, in _ensure_repository 2026-06-25 11:18:48.771 work_tree.init_repo() 2026-06-25 11:18:48.771 File "/snap/snapcraft/18124/lib/python3.12/site-packages/craft_application/remote/worktree.py", line 54, in init_repo 2026-06-25 11:18:48.771 copytree(self._project_dir, self._repo_dir) 2026-06-25 11:18:48.771 File "/snap/snapcraft/current/usr/lib/python3.12/shutil.py", line 600, in copytree 2026-06-25 11:18:48.771 return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks, 2026-06-25 11:18:48.771 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-06-25 11:18:48.771 File "/snap/snapcraft/current/usr/lib/python3.12/shutil.py", line 554, in _copytree 2026-06-25 11:18:48.771 raise Error(errors) 2026-06-25 11:18:48.771 shutil.Error: [('/home/imani/work/scratch/here', '/home/imani/.cache/snapcraft/remote-build/snapcraft-scratch-a22566aae87cb46312173f84fc845a49/repo/here', "[Errno 2] No such file or directory: '/home/imani/work/scratch/here'")] 2026-06-25 11:18:48.771 Full execution log: '/home/imani/.local/state/snapcraft/log/snapcraft-20260625-111842.312392.log' ```

Evaluation history

Date Model Scores Action Summary
stealth/space-bunny-alpha — closed resolved remote-build crashed with shutil.Error on dangling symlinks because worktree copytree used default symlinks=False. Fixed by merged PR #1104 (commit 8256b7a2), which passes ignore_dangling_symlinks=True to copytree; released in 7.1.1.
stealth/space-bunny-alpha — closed resolved Remote builds with dangling symlinks were fixed by merged craft-application PR #1104, which skips broken symlinks during work-tree copying for version 7.1.1.
qwen/qwen3.6-35b-a3b — — Closed without resolution. Remote-build crashes during project directory copying when dangling symlinks are present, causing a shutil.Error. No fix or follow-up was provided.
qwen3.6-35b-a3b-mtp-q6
Impact: 50
Quick Win: 42
Staleness: 65
Complexity: 15
Confidence: 70
Support Request: 0
needs triage Remote build fails on dangling symlinks due to copytree not handling them. Issue has no maintainer response or labels after 71 days. Related PR #1100 was closed without merging.
qwen/qwen3.6-35b-a3b
Staleness: 40
Complexity: 30
Confidence: 90
Support Request: 0
needs triage Remote build fails with shutil.Error when project contains dangling symlinks. Reported by maintainer 26 days ago with clear reproduction steps and traceback, but currently unlabelled and awaiting triage.
qwen3.6-35b-a3b-mtp-q6
Staleness: 40
Complexity: 35
Confidence: 95
Support Request: 5
needs triage remote-build fails when copying project directories containing dangling symlinks, raising a shutil.Error during repository initialization. Unlabelled, 14 days old, awaiting maintainer triage.

Update history

Date Change
closed

Related work

  • Likely Fixed By: canonical/craft-application#1104 (confidence 95%)

    Merged PR fixing the issue; commit 8256b7a2 adds ignore_dangling_symlinks=True to the worktree copytree call, shipped in version 7.1.1.

  • Related To: canonical/craft-application#721 (confidence 70%)

    Open issue 'Don't follow symlinks for remote-builds'; broader request that worktree copying not follow symlinks and handle copy failures. Only the dangling-symlink skipping from #1104 landed.

Related issues

Issue Project State Summary Similarity
#1104 fix(remote-build): ignore dangling symlinks craft-application merged Merged PR #1104 (commit 8256b7a2) makes remote-build copy the work tree with ignore_dangling_symlinks=True, fixing #1103. Merge conflicts resolved and changelog entry shipped under 7.1.1.
86%
#721 Don't follow symlinks for remote-builds craft-application open Remote-build worktree copy still follows symlinks and has no try/except around copytree, so copy failures bubble up as internal errors. Only dangling-symlink skipping (PR #1104) landed.
84%
#1100 fix(remotebuild): allow building projects with dangling symlinks craft-application closed PR #1100 by mr-cal fixed remote builds failing on dangling symlinks, but was closed unmerged in favour of @bepri's PR #1104, which merged the same fix for #1103 in craft-application 7.1.1.
75%