← Back to issue list

Packing a charm sometimes fails with "Too many levels of symbolic links"

View original Github issue

Metadata

Project
charmcraft
Number
#2661
Type
issue
State
open
Author
dwilding
Labels
Created
2026-04-21 05:19:03+00:00
Updated
2026-04-22 17:48:53+00:00
Closed

Current evaluation

Charm packing fails with a symbolic link error when .tox or .venv directories are present, and the issue remains open with contributors actively reproducing it and discussing workarounds.

Suggested action: needs triage

Reason: The issue is a valid bug report but lacks maintainer labels, assignees, or prior assessment. It requires initial triage to verify reproducibility, prioritize, and categorize appropriately.

Staleness: 25 Complexity: 40 Confidence: 85 Support Request: 0

Issue body

### Check existing issues - [x] I've verified that this bug isn't described by any existing issues. ### Bug description Packing a charm that has a `.tox` or a `.venv` directory can fail with a "Too many levels of symbolic links" error: ```text OSError: [Errno 40] Too many levels of symbolic links: '/root/project/.tox/lint/lib64' ``` and ```text OSError: [Errno 40] Too many levels of symbolic links: '/home/ubuntu/tinyproxy/.venv/bin/python3.12' ``` See the log output below for more context. I haven't been able to reproduce this myself, but @james-garner-canonical and I have observed other people running into the issue. The context is: - Working inside a Multipass VM on a Mac - Used tox to run a development command (so that `.tox` is created) or used uv to manage the charm's dependencies (so that `.venv` is created) - Then packed the charm, not using destructive mode If packing fails, deleting `.tox`/`.venv` before packing again seems to help. Using destructive mode seems to help. (I'm sorry these resolution steps aren't more precise.) ### Steps to reproduce See above ### Environment Multipass on a Mac. Not destructive mode. ### charmcraft.yaml ```yaml # This file configures Charmcraft. # See https://documentation.ubuntu.com/charmcraft/stable/reference/files/charmcraft-yaml-file/ type: charm name: tinyproxy title: Reverse Proxy Demo summary: A demo charm that configures tinyproxy as a reverse proxy. description: | This charm demonstrates how to write a machine charm with Ops. # Documentation: # https://documentation.ubuntu.com/charmcraft/stable/howto/build-guides/select-platforms/ base: ubuntu@24.04 platforms: amd64: arm64: assumes: - juju >= 3.6 parts: charm: plugin: uv source: . build-snaps: - astral-uv # (Optional) Configuration options for the charm # This config section defines charm config options, and populates the Configure # tab on Charmhub. # More information on this section at: # https://documentation.ubuntu.com/charmcraft/stable/reference/files/charmcraft-yaml-file/#config # General configuration documentation: # https://documentation.ubuntu.com/juju/3.6/reference/configuration/#application-configuration config: options: slug: description: "Configures the path of the reverse proxy. Must match the regex [a-z0-9-]+" default: example type: string ``` ### Log output ```shell :: ## User environment :: 2026-03-26 08:32:23.513 plugin validation command: 'uv --version' :: 2026-03-26 08:32:23.739 executed uv --version with output uv 0.11.1 (a6042f67f 2026-03-24 aarch64-unknown-linux-gnu) :: 2026-03-26 08:32:23.739 set repository attribute: attr=stage_packages_filters, value=None, repo:<class 'craft_parts.packages.deb.Ubuntu'> :: 2026-03-26 08:32:23.739 Pulling charm :: 2026-03-26 08:32:23.739 execute action charm:Action(part_name='charm', step=Step.PULL, action_type=ActionType.RUN, reason=None, project_vars=ProjectVarInfo(root={}), properties=ActionProperties(changed_files=None, changed_dirs=None)) :: 2026-03-26 08:32:23.921 /root/project/.tox/lint/lib64: Too many levels of symbolic links :: 2026-03-26 08:32:23.921 Detailed information: OSError: filename: '/root/project/.tox/lint/lib64' :: 2026-03-26 08:32:23.924 Traceback (most recent call last): :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 96, in link_or_copy :: 2026-03-26 08:32:23.924 copy(source, destination) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 173, in copy :: 2026-03-26 08:32:23.924 shutil.copy2(source, destination, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/current/usr/lib/python3.12/shutil.py", line 476, in copy2 :: 2026-03-26 08:32:23.924 copystat(src, dst, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/current/usr/lib/python3.12/shutil.py", line 388, in copystat :: 2026-03-26 08:32:23.924 _copyxattr(src, dst, follow_symlinks=follow) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/current/usr/lib/python3.12/shutil.py", line 330, in _copyxattr :: 2026-03-26 08:32:23.924 names = os.listxattr(src, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: 2026-03-26 08:32:23.924 OSError: [Errno 40] Too many levels of symbolic links: '/root/project/.tox/lint/lib64' :: 2026-03-26 08:32:23.924 :: 2026-03-26 08:32:23.924 During handling of the above exception, another exception occurred: :: 2026-03-26 08:32:23.924 Traceback (most recent call last): :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 318, in run :: 2026-03-26 08:32:23.924 self._exec(actions) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 342, in _exec :: 2026-03-26 08:32:23.924 aex.execute(action, stdout=stream, stderr=stream) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 342, in execute :: 2026-03-26 08:32:23.924 self._executor.execute(actions, stdout=stdout, stderr=stderr) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 136, in execute :: 2026-03-26 08:32:23.924 self._run_action(act, stdout=stdout, stderr=stderr) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 229, in _run_action :: 2026-03-26 08:32:23.924 handler.run_action(action, stdout=stdout, stderr=stderr) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 309, in run_action :: 2026-03-26 08:32:23.924 state = handler(step_info, stdout=stdout, stderr=stderr) :: 2026-03-26 08:32:23.924 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 335, in _run_pull :: 2026-03-26 08:32:23.924 self._run_step( :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 674, in _run_step :: 2026-03-26 08:32:23.924 return step_handler.run_builtin() :: 2026-03-26 08:32:23.924 ^^^^^^^^^^^^^^^^^^^^^^^^^^ :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/step_handler.py", line 139, in run_builtin :: 2026-03-26 08:32:23.924 return handler() :: 2026-03-26 08:32:23.924 ^^^^^^^^^ :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/executor/step_handler.py", line 143, in _builtin_pull :: 2026-03-26 08:32:23.924 self._source_handler.pull() :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/sources/local_source.py", line 105, in pull :: 2026-03-26 08:32:23.924 file_utils.link_or_copy_tree( :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 255, in link_or_copy_tree :: 2026-03-26 08:32:23.924 copy_function(source, destination) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 111, in link_or_copy :: 2026-03-26 08:32:23.924 copy(source, destination, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 173, in copy :: 2026-03-26 08:32:23.924 shutil.copy2(source, destination, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/current/usr/lib/python3.12/shutil.py", line 476, in copy2 :: 2026-03-26 08:32:23.924 copystat(src, dst, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/current/usr/lib/python3.12/shutil.py", line 388, in copystat :: 2026-03-26 08:32:23.924 _copyxattr(src, dst, follow_symlinks=follow) :: 2026-03-26 08:32:23.924 File "/snap/charmcraft/current/usr/lib/python3.12/shutil.py", line 330, in _copyxattr :: 2026-03-26 08:32:23.924 names = os.listxattr(src, follow_symlinks=follow_symlinks) :: 2026-03-26 08:32:23.924 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: 2026-03-26 08:32:23.924 OSError: [Errno 40] Too many levels of symbolic links: '/root/project/.tox/lint/lib64' 2026-03-26 08:32:24.278 Executing on host: lxc --project charmcraft config device show local:charmcraft-tinyproxy-arm64-975 2026-03-26 08:32:24.347 Executing on host: lxc --project charmcraft config device remove local:charmcraft-tinyproxy-arm64-975 disk-/root/.cache/pip 2026-03-26 08:32:24.433 Executing on host: lxc --project charmcraft config device remove local:charmcraft-tinyproxy-arm64-975 disk-/root/project 2026-03-26 08:32:24.513 Executing on host: lxc --project charmcraft config device remove local:charmcraft-tinyproxy-arm64-975 disk-/tmp/craft-state 2026-03-26 08:32:24.599 Executing on host: lxc --project charmcraft stop local:charmcraft-tinyproxy-arm64-975 2026-03-26 08:32:28.532 Executing on host: lxc --project charmcraft list local: --format=yaml 2026-03-26 08:32:28.613 Executing on host: lxc --project charmcraft list local: --format=yaml 2026-03-26 08:32:28.735 Executing on host: lxc --project charmcraft list local: --format=yaml 2026-03-26 08:32:28.880 Executing on host: lxc --project charmcraft config set local:charmcraft-tinyproxy-arm64-975 user.craft_providers.status FINISHED 2026-03-26 08:32:28.969 Failed to run charmcraft in instance 2026-03-26 08:32:28.980 Traceback (most recent call last): 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/services/provider.py", line 471, in run_managed 2026-03-26 08:32:28.980 instance.execute_run( # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType] 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_providers/lxd/lxd_instance.py", line 257, in execute_run 2026-03-26 08:32:28.980 return self.lxc.exec( 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_providers/lxd/lxc.py", line 393, in exec 2026-03-26 08:32:28.980 return runner(final_cmd, timeout=timeout, check=check, **kwargs) 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/current/usr/lib/python3.12/subprocess.py", line 571, in run 2026-03-26 08:32:28.980 raise CalledProcessError(retcode, process.args, 2026-03-26 08:32:28.980 subprocess.CalledProcessError: Command '['lxc', '--project', 'charmcraft', 'exec', 'local:charmcraft-tinyproxy-arm64-975', '--cwd', '/root/project', '--', 'env', 'CRAFT_MANAGED_MODE=1', 'CHARMCRAFT_DEBUG=False', 'CHARMCRAFT_LXD_REMOTE=local', 'CHARMCRAFT_LAUNCHPAD_INSTANCE=production', 'CHARMCRAFT_MANAGED_MODE=1', 'DEBIAN_FRONTEND=noninteractive', 'DEBCONF_NONINTERACTIVE_SEEN=true', 'DEBIAN_PRIORITY=critical', 'CRAFT_PLATFORM=arm64', 'CRAFT_VERBOSITY_LEVEL=BRIEF', 'charmcraft', 'pack']' returned non-zero exit status 1. 2026-03-26 08:32:28.980 2026-03-26 08:32:28.980 The above exception was the direct cause of the following exception: 2026-03-26 08:32:28.980 Traceback (most recent call last): 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/application.py", line 663, in run 2026-03-26 08:32:28.980 return_code = self._run_inner() 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/charmcraft/application/main.py", line 143, in _run_inner 2026-03-26 08:32:28.980 return super()._run_inner() 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/application.py", line 640, in _run_inner 2026-03-26 08:32:28.980 return_code = dispatcher.run() or os.EX_OK 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_cli/dispatcher.py", line 564, in run 2026-03-26 08:32:28.980 return self._loaded_command.run(self._parsed_command_args) 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/commands/base.py", line 200, in run 2026-03-26 08:32:28.980 result = self._run(parsed_args, **kwargs) or result 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/charmcraft/application/commands/lifecycle.py", line 167, in _run 2026-03-26 08:32:28.980 result = super()._run(parsed_args, step_name, **kwargs) 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 619, in _run 2026-03-26 08:32:28.980 return super()._run(parsed_args=parsed_args, step_name=step_name) 2026-03-26 08:32:28.980 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 232, in _run 2026-03-26 08:32:28.980 self._run_manager_for_build_plan(fetch_service_policy) 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 97, in _run_manager_for_build_plan 2026-03-26 08:32:28.980 provider.run_managed(build, bool(fetch_service_policy)) 2026-03-26 08:32:28.980 File "/snap/charmcraft/7519/lib/python3.12/site-packages/craft_application/services/provider.py", line 478, in run_managed 2026-03-26 08:32:28.980 raise craft_providers.ProviderError( 2026-03-26 08:32:28.980 craft_providers.errors.ProviderError: Failed to run charmcraft in instance 2026-03-26 08:32:28.980 Full execution log: '/home/ubuntu/.local/state/charmcraft/log/charmcraft-20260326-082831.211082.log' ```

Evaluation history

Date Model Scores Action Summary
2026-06-15 11:55:59.964838+00:00 qwen3.6-35b-a3b-mtp-q6
Staleness: 25
Complexity: 40
Confidence: 85
Support Request: 0
needs triage Charm packing fails with a symbolic link error when .tox or .venv directories are present, and the issue remains open with contributors actively reproducing it and discussing workarounds.
2026-06-15 11:53:46.305460+00:00 pending