Skip to content

Can't "build-time resolve" staged symlinks with organize #6168

@Saviq

Description

@Saviq

Check existing issues

  • I've verified that this bug isn't described by any existing issues.

Bug description

When a part stages a symlink to another folder in itself, there's no way to organize: that away. Even if you unstage the original symlink, the copying process is still stepping on its own toes.

Steps to reproduce

snapcraft pack the attached YAML

Environment

Just a normal snapcraft pack on Ubuntu.

snapcraft.yaml

name: xkb-test
base: core26
build-base: devel
version: '0.1'
summary: Single-line elevator pitch for your amazing snap
description: Description

grade: devel
confinement: strict

parts:
  my-part:
    plugin: nil
    stage-packages:
    - xkb-data
    stage:
    - -usr/share/X11/xkb
    organize:
      usr/share/xkeyboard-config-2: usr/share/X11/xkb

Log output

:: 2026-04-10 13:13:29.831 remove directory /root/parts/my-part/build
:: 2026-04-10 13:13:29.832 Executing PosixPath('/root/parts/my-part/run/build.sh')
:: 2026-04-10 13:13:29.834 Failed to copy '/root/parts/my-part/install/usr/share/xkeyboard-config-2/keycodes/README': no such file or directory.
:: 2026-04-10 13:13:29.839 Traceback (most recent call last):
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 98, in link_or_copy
:: 2026-04-10 13:13:29.839     link(source, destination, follow_symlinks=follow_symlinks)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 142, in link
:: 2026-04-10 13:13:29.839     os.link(source_path, destination, follow_symlinks=False)
:: 2026-04-10 13:13:29.839 FileExistsError: [Errno 17] File exists: '/root/parts/my-part/install/usr/share/xkeyboard-config-2/keycodes/README' -> '/root/parts/my-part/install/usr/share/X11/xkb/keycodes/README'
:: 2026-04-10 13:13:29.839 
:: 2026-04-10 13:13:29.839 During handling of the above exception, another exception occurred:
:: 2026-04-10 13:13:29.839 Traceback (most recent call last):
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 142, in link
:: 2026-04-10 13:13:29.839     os.link(source_path, destination, follow_symlinks=False)
:: 2026-04-10 13:13:29.839 FileNotFoundError: [Errno 2] No such file or directory: '/root/parts/my-part/install/usr/share/xkeyboard-config-2/keycodes/README' -> '/root/parts/my-part/install/usr/share/X11/xkb/keycodes/README'
:: 2026-04-10 13:13:29.839 
:: 2026-04-10 13:13:29.839 The above exception was the direct cause of the following exception:
:: 2026-04-10 13:13:29.839 Traceback (most recent call last):
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 355, in run
:: 2026-04-10 13:13:29.839     self._exec(actions)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 379, in _exec
:: 2026-04-10 13:13:29.839     aex.execute(action, stdout=stream, stderr=stream)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 353, in execute
:: 2026-04-10 13:13:29.839     self._executor.execute(actions, stdout=stdout, stderr=stderr)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 153, in execute
:: 2026-04-10 13:13:29.839     self._run_action(act, stdout=stdout, stderr=stderr)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 246, in _run_action
:: 2026-04-10 13:13:29.839     handler.run_action(action, stdout=stdout, stderr=stderr)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 313, in run_action
:: 2026-04-10 13:13:29.839     state = handler(step_info, stdout=stdout, stderr=stderr)
:: 2026-04-10 13:13:29.839             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 484, in _run_build
:: 2026-04-10 13:13:29.839     organize_files(
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/executor/organize.py", line 84, in organize_files
:: 2026-04-10 13:13:29.839     file_utils.link_or_copy_tree(src, dst)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 255, in link_or_copy_tree
:: 2026-04-10 13:13:29.839     copy_function(source, destination)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 104, in link_or_copy
:: 2026-04-10 13:13:29.839     link_or_copy(
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 98, in link_or_copy
:: 2026-04-10 13:13:29.839     link(source, destination, follow_symlinks=follow_symlinks)
:: 2026-04-10 13:13:29.839   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 144, in link
:: 2026-04-10 13:13:29.839     raise errors.CopyFileNotFound(source) from err
:: 2026-04-10 13:13:29.839 craft_parts.errors.CopyFileNotFound: Failed to copy '/root/parts/my-part/install/usr/share/xkeyboard-config-2/keycodes/README': no such file or directory.
2026-04-10 13:13:30.393 Executing on host: lxc --project snapcraft config device show local:snapcraft-xkb-test-amd64-18059
2026-04-10 13:13:30.557 Executing on host: lxc --project snapcraft config device remove local:snapcraft-xkb-test-amd64-18059 disk-/root/project
2026-04-10 13:13:30.742 Executing on host: lxc --project snapcraft config device remove local:snapcraft-xkb-test-amd64-18059 disk-/tmp/craft-state
2026-04-10 13:13:30.922 Executing on host: lxc --project snapcraft stop local:snapcraft-xkb-test-amd64-18059
2026-04-10 13:13:34.892 Executing on host: lxc --project snapcraft list local: --format=yaml
2026-04-10 13:13:35.143 Executing on host: lxc --project snapcraft config set local:snapcraft-xkb-test-amd64-18059 user.craft_providers.status FINISHED
2026-04-10 13:13:35.345 Failed to run snapcraft in instance
2026-04-10 13:13:35.347 Traceback (most recent call last):
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/services/provider.py", line 503, in run_managed
2026-04-10 13:13:35.347     instance.execute_run(  # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_providers/lxd/lxd_instance.py", line 272, in execute_run
2026-04-10 13:13:35.347     return self.lxc.exec(
2026-04-10 13:13:35.347            ^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_providers/lxd/lxc.py", line 528, in exec
2026-04-10 13:13:35.347     return runner(final_cmd, timeout=timeout, check=check, **kwargs)
2026-04-10 13:13:35.347            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/current/usr/lib/python3.12/subprocess.py", line 571, in run
2026-04-10 13:13:35.347     raise CalledProcessError(retcode, process.args,
2026-04-10 13:13:35.347 subprocess.CalledProcessError: Command '['lxc', '--project', 'snapcraft', 'exec', 'local:snapcraft-xkb-test-amd64-18059', '--cwd', '/root/project', '--', 'env', 'CRAFT_MANAGED_MODE=1', 'SNAPCRAFT_DEBUG=False', 'SNAPCRAFT_LXD_REMOTE=local', 'SNAPCRAFT_LAUNCHPAD_INSTANCE=production', 'DEBIAN_FRONTEND=noninteractive', 'DEBCONF_NONINTERACTIVE_SEEN=true', 'DEBIAN_PRIORITY=critical', 'CRAFT_PLATFORM=amd64', 'CRAFT_VERBOSITY_LEVEL=VERBOSE', 'snapcraft', '--verbose', 'pack']' returned non-zero exit status 1.
2026-04-10 13:13:35.347 
2026-04-10 13:13:35.347 The above exception was the direct cause of the following exception:
2026-04-10 13:13:35.347 Traceback (most recent call last):
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/application.py", line 678, in run
2026-04-10 13:13:35.347     return_code = self._run_inner()
2026-04-10 13:13:35.347                   ^^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/snapcraft/application.py", line 182, in _run_inner
2026-04-10 13:13:35.347     return_code = super()._run_inner()
2026-04-10 13:13:35.347                   ^^^^^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/application.py", line 655, in _run_inner
2026-04-10 13:13:35.347     return_code = dispatcher.run() or os.EX_OK
2026-04-10 13:13:35.347                   ^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_cli/dispatcher.py", line 576, in run
2026-04-10 13:13:35.347     return self._loaded_command.run(self._parsed_command_args)
2026-04-10 13:13:35.347            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/commands/base.py", line 222, in run
2026-04-10 13:13:35.347     result = self._run(parsed_args, **kwargs) or result
2026-04-10 13:13:35.347              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/snapcraft/commands/lifecycle.py", line 74, in _run
2026-04-10 13:13:35.347     super()._run(parsed_args)
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 627, in _run
2026-04-10 13:13:35.347     return super()._run(parsed_args=parsed_args, step_name=step_name)
2026-04-10 13:13:35.347            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 240, in _run
2026-04-10 13:13:35.347     self._run_manager_for_build_plan(fetch_service_policy)
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 105, in _run_manager_for_build_plan
2026-04-10 13:13:35.347     provider.run_managed(build, bool(fetch_service_policy))
2026-04-10 13:13:35.347   File "/snap/snapcraft/17521/lib/python3.12/site-packages/craft_application/services/provider.py", line 510, in run_managed
2026-04-10 13:13:35.347     raise craft_providers.ProviderError(
2026-04-10 13:13:35.347 craft_providers.errors.ProviderError: Failed to run snapcraft in instance

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions