← Back to issue list

`organize` part expects distinct subdirectories since 4.2.1

View original Github issue

Metadata

Project
charmcraft
Number
#2720
Type
issue
State
open
Author
natalian98
Labels
—
Created
Updated
Closed
—

Current evaluation

Charmcraft 4.2.1 regressed dump-part organize: two glob mappings targeting schemas/ now fail; distinct subdirectories work around it, and the report remains untriaged.

Suggested action: needs triage

Reason: The report provides an exact repository, configuration, commands, full error, and version boundary: 4.0.1 succeeds, 4.2.1 fails, and distinct destinations work. The traceback points to craft_parts.executor.organize.organize_files, but with no labels, maintainer response, or confirmation of intended semantics, upstream ownership and whether the behavior remains unresolved still need assessment.

Evaluated by: mr-cal-bot

Impact: 56 Quick Win: 20 Complexity: 59 Confidence: 84 Actionability: 87

Issue body

### Check existing issues - [x] I've verified that this bug isn't described by any existing issues. ### Bug description Since the 4.2.1 charmcraft release, one of our charms (kratos-operator) started to fail when packing. Specifically this part: ``` parts: schemas: plugin: dump source: . organize: "claim_mappers/**": schemas/ "identity_schemas/**": schemas/ prime: - schemas/ ``` It seems that we can't use the same schemas directory for more than one key anymore: ``` :: 2026-05-28 16:02:05.414 :: + cp --archive --link --no-dereference . /root/parts/schemas/install :: 2026-05-28 16:02:05.426 Run pre-organize callbacks :: 2026-05-28 16:02:05.429 Failed to organize part 'schemas': trying to organize 'identity_schemas/**' to 'schemas/', but 'schemas/' already exists. :: 2026-05-28 16:02:05.438 Traceback (most recent call last): :: 2026-05-28 16:02:05.438   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 355, in run :: 2026-05-28 16:02:05.438     self._exec(actions) :: 2026-05-28 16:02:05.438   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 379, in _exec :: 2026-05-28 16:02:05.438     aex.execute(action, stdout=stream, stderr=stream) :: 2026-05-28 16:02:05.438   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 353, in execute :: 2026-05-28 16:02:05.438     self._executor.execute(actions, stdout=stdout, stderr=stderr) :: 2026-05-28 16:02:05.438   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 153, in execute :: 2026-05-28 16:02:05.438     self._run_action(act, stdout=stdout, stderr=stderr) :: 2026-05-28 16:02:05.438   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 246, in _run_action :: 2026-05-28 16:02:05.438     handler.run_action(action, stdout=stdout, stderr=stderr) :: 2026-05-28 16:02:05.439   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 313, in run_action :: 2026-05-28 16:02:05.439     state = handler(step_info, stdout=stdout, stderr=stderr) :: 2026-05-28 16:02:05.439             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: 2026-05-28 16:02:05.439   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 487, in _run_build :: 2026-05-28 16:02:05.439     organize_files( :: 2026-05-28 16:02:05.439   File "/snap/charmcraft/7759/lib/python3.12/site-packages/craft_parts/executor/organize.py", line 129, in organize_files :: 2026-05-28 16:02:05.439     raise errors.FileOrganizeError( :: 2026-05-28 16:02:05.439 craft_parts.errors.FileOrganizeError: Failed to organize part 'schemas': trying to organize 'identity_schemas/**' to 'schemas/', but 'schemas/' already exists. ``` The charm was packing fine with 4.0.1. With 4.2.1, it is packed successfully once switched to `"claim_mappers/**": schemas/claim_mappers "identity_schemas/**": schemas/identity_schemas` (distinct subdirectories) but I'm wondering if this was intentional. ### Steps to reproduce git clone https://github.com/canonical/kratos-operator.git && cd kratos-operator charmcraft pack -v ### Environment ubuntu 24.04 ### charmcraft.yaml ```yaml # Copyright 2025 Canonical Ltd. # See LICENSE file for licensing details. name: kratos type: charm description: | Charmed Ory Kratos summary: | Identity and user management system links: documentation: https://canonical-identity.readthedocs-hosted.com/reference/charms/kratos source: https://github.com/canonical/kratos-operator issues: https://github.com/canonical/kratos-operator/issues containers: kratos: resource: oci-image resources: oci-image: type: oci-image description: Kratos oci-image upstream-source: ghcr.io/canonical/kratos:25.4.0 verification-email-template: type: file filename: verification-email-template.gotmpl description: Custom email verification template to use with code method requires: pg-database: interface: postgresql_client optional: false kratos-external-idp: interface: external_provider optional: true hydra-endpoint-info: interface: hydra_endpoints limit: 1 optional: true ui-endpoint-info: interface: login_ui_endpoints optional: true kratos-registration-webhook: interface: kratos_registration_webhook optional: true kratos-login-webhook: interface: kratos_login_webhook optional: true logging: interface: loki_push_api optional: true tracing: interface: tracing limit: 1 optional: true description: | Provides traces to COS Tempo instance smtp: interface: smtp limit: 1 optional: true internal-route: interface: traefik_route limit: 1 optional: true description: | Ingress used for cross-cluster communication where network topology is more complex than just one k8s cluster public-route: interface: traefik_route optional: true description: | Recommended way to expose the charm to the public internet receive-ca-cert: interface: certificate_transfer optional: true description: | Receive a CA cert. This relation can be used with a local CA to obtain the CA cert that was used to sign proxied endpoints. peers: kratos-peers: interface: kratos-peers provides: kratos-info: interface: kratos_info description: | Provides kratos deployment info to a related application optional: true metrics-endpoint: interface: prometheus_scrape description: | Provides application metrics to COS Prometheus instance optional: true grafana-dashboard: description: | Forwards the built-in grafana dashboard(s) for monitoring kratos. interface: grafana_dashboard optional: true config: options: http_proxy: description: URL of the HTTP proxy eg http://proxy.internal:6666, it will set the HTTP_PROXY var in the workload environment type: string default: '' https_proxy: description: URL of the HTTPS proxy eg http://proxy.internal:6666, it will set the HTTPS_PROXY var in the workload environment type: string default: '' no_proxy: description: Domains that need to be excluded from proxying no_proxy="test.com,test.co.uk", it is a comma separate list type: string default: '' cpu: description: | K8s cpu resource limit, e.g. "1" or "500m". Default is unset (no limit). This value is used for the "limits" portion of the resource requirements (the "requests" portion is automatically deduced from it). See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: string memory: description: | K8s memory resource limit, e.g. "1Gi". Default is unset (no limit). This value is used for the "limits" portion of the resource requirements (the "requests" portion is automatically deduced from it). See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: string dev: description: Run Kratos on dev mode, it is needed if HTTPS is not set up. This should only be used for development purposes. type: boolean default: False enable_local_idp: description: Enable Kratos Identity Provider type: boolean default: True enforce_mfa: description: | Enforce users to set up and use multi factor authentication. Disabling this option will allow users to log in with password or webauthn without completing 2fa. type: boolean default: True enable_verification: description: | Enable and enforce users to verify their accounts. Enabling this option will make users verify their accounts after registration or on the next login. This option requires an SMTP server integration. type: boolean default: False sender_email: description: | The email address used as the sender for automated verification and recovery emails. type: string default: "identity@canonical.com" sender_name: description: | The display name that appears alongside the sender email address in recovery and verification emails. type: string default: "Canonical Identity Platform" enable_passwordless_login_method: description: | Enable passwordless authentication via webauthn. Requires `enable_local_idp=True`. type: boolean default: False enable_oidc_webauthn_sequencing: description: | Enforce setting up a WebAuthn key (e.g. with YubiKey or Google Password Manager on Android) after signing in with an external identity provider. Requires `enable_passwordless_login_method=False`. WARNING: Do not enable this option unless you are sure that this feature applies to your deployment. type: boolean default: False identity_schemas: description: | A mapping of schema_id to identity schemas. For example: { "user_v0": { "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "Person", "type": "object", "properties": { "traits": { "type": "object", "properties": { "email": { "type": "string", "format": "email", "title": "E-Mail", "minLength": 3, "ory.sh/kratos": { "verification": { "via": "email" } } }, "name": { "type": "string" } } }, "additionalProperties": true } } } type: string default_identity_schema_id: description: The default identity schema id, this option only works when `identity_schemas` is defined type: string recovery_email_template: description: | The custom html template used to send emails with recovery codes. For example: Hi, Please enter the following code to recover your account: {{ .RecoveryCode }} type: string log_level: description: | The verbosity of logs produced by Kratos. Available values are: panic, fatal, error, warn, info, debug, and trace. type: string default: "info" actions: get-identity: description: Get a user using either the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string delete-identity: description: Delete a user using the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string create-admin-account: description: | Create an admin user. If no password was provided, the command will return a magic link where the user will be able to set their password. params: username: description: The admin username type: string email: description: | The admin's email, this email must not be associated with any other account (user or admin) type: string password-secret-id: description: The juju secret that contains the admin's password type: string name: description: The admin's name type: string phone-number: description: The admin's phone number type: string required: - username - email reset-password: description: | Reset password of an identity using the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string password-secret-id: description: | The juju secret that contains the password to set for an identity. If not provided, a self-service recovery link will be returned. type: string invalidate-identity-sessions: description: | Invalidate all user sessions using the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string reset-identity-mfa: description: | Reset identity's second authentication factor using the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string mfa-type: description: The type of credentials to be removed, one of `totp`, `lookup_secret` or `webauthn`. type: string enum: - totp - lookup_secret - webauthn required: - mfa-type list-oidc-accounts: description: | Retrieve the list of OIDC accounts identifiers linked to an identity using the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string unlink-oidc-account: description: | Unlink a user's external identity provider account from their identity using the identity ID or the user email. params: identity-id: description: The Identity ID type: string email: description: The user's email type: string credential-id: description: The OIDC credential ID to unlink. Run `list-identity-linked-oidc-accounts` to list available credentials. type: string required: - credential-id run-migration: description: | Run a migration, this is needed after upgrades. This is a non-reversible operation. Run this after backing up the database. params: timeout: description: Timeout after which the migration will be canceled type: number default: 120 ########################### build ########################### platforms: ubuntu@22.04:amd64: parts: schemas: plugin: dump source: . organize: "claim_mappers/**": schemas/ "identity_schemas/**": schemas/ prime: - schemas/ charm: charm-binary-python-packages: - jsonschema - bcrypt - "setuptools>=70.0.0" build-packages: - "rustc-1.85" - "cargo-1.85" ``` ### Log output ```shell ```

Evaluation history

Date Model Scores Action Summary
stealth/space-bunny-alpha
Impact: 56
Quick Win: 20
Complexity: 59
Confidence: 84
Actionability: 87
needs triage Charmcraft 4.2.1 regressed dump-part organize: two glob mappings targeting schemas/ now fail; distinct subdirectories work around it, and the report remains untriaged.
stealth/space-bunny-alpha
Impact: 48
Quick Win: 24
Complexity: 45
Confidence: 84
Actionability: 91
needs triage Reported Charmcraft 4.2.1 regression: multiple glob-based organize mappings to schemas/ fail with FileOrganizeError, breaking kratos-operator packing; distinct subdirectories work around it.
stealth/space-bunny-alpha
Impact: 50
Quick Win: 10
Complexity: 65
Confidence: 88
Actionability: 55
needs triage Charmcraft 4.2.1 packaging regressed: the organize step rejects multiple source patterns targeting the same schemas/ directory; a reproducible charmcraft.yaml and successful workaround are provided.
qwen3.6-35b-a3b-mtp-q6
Impact: 50
Quick Win: 30
Staleness: 55
Complexity: 40
Confidence: 60
Support Request: 20
needs triage Regression in craft-parts where organizing multiple source patterns to the same destination directory now fails with FileOrganizeError since version 4.2.1
qwen/qwen3.6-35b-a3b
Staleness: 55
Complexity: 30
Confidence: 85
Support Request: 10
needs triage Regression in charmcraft 4.2.1 where craft-parts organize step fails when multiple source globs map to the same destination directory. Untriaged, no maintainer response.
qwen3.6-35b-a3b-mtp-q6
Staleness: 30
Complexity: 45
Confidence: 90
Support Request: 5
needs triage Regression in charmcraft 4.2.1 where craft-parts organize step fails when multiple source globs map to the same destination directory. Untriaged, awaiting maintainer review.

Update history

No update history recorded yet.

Related work

  • Related To: canonical/craft-parts#1366 (confidence 70%)

    Closed by PR #1370 (7fe7c84e) for destination-existence checks in the same organizer; relevant to investigation, but not proof that shared glob destinations are fixed.

Related issues

No related issues found above the similarity threshold.