organize with `app: app/app` is not working correctly
Metadata
Current evaluation
fastapi-framework extension fails to pack when app code is in app/ directory; generated organize app: app/app causes FileNotFoundError in craft-parts. No maintainer response; root cause tracked in craft-parts#1460.
Suggested action: needs triage
Reason: The issue has no labels or maintainer response; only a contributor asked to be assigned. It is a clear, reproducible bug with exact files and logs, but the root cause is in craft-parts and is tracked in canonical/craft-parts#1460, which remains open.
Evaluated by: mr-cal-bot
Impact:
45
Quick Win:
13
Complexity:
65
Confidence:
75
Actionability:
80
Issue body
### Bug Description
I have followed the [fastapi tutorial](https://documentation.ubuntu.com/rockcraft/en/latest/tutorial/fastapi/), but instead of creating the file `app.py` in the base directory, I have created the file `main.py` inside the directory `app`.
That is, the tree of the files is:
```
ubuntu@paas-charm:~/delete/fastapi-hello-world$ tree
.
├── app
│ ├── __init__.py
│ └── main.py
├── requirements.txt
└── rockcraft.yaml
```
Running `ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=true rockcraft pack` I get the error:
```
*EXPERIMENTAL* extension 'fastapi-framework' enabled
/root/parts/fastapi-framework/install-app/install/app: No such file or directory
Detailed information: FileNotFoundError: filename: '/root/parts/fastapi-framework/install-app/install/app'
Failed to run rockcraft in instance
Full execution log: '/home/ubuntu/.local/state/rockcraft/log/rockcraft-20250530-174607.442030.log'
```
The reason looks related to the part `fastapi-framework/install-app`. Running `rockcraft expand-extensions`, that part shows:
```
fastapi-framework/install-app:
plugin: dump
source: .
organize:
app: app/app
stage:
- app/app
```
However, the directory app/app is not in the install directory in the lxd machine to build the rock.
```
rockcraft-fastapi-hello-world-amd64-7078398 # ls parts/fastapi-framework/install-app/
build export install layer run src state
```
### To Reproduce
Inside a directory named `fastapi-hello-world`
File requirements.txt
```
fastapi[standard]>=0.109.1
```
File rockcraft.yaml:
```
name: fastapi-hello-world
base: ubuntu@24.04 # the base environment for this FastAPI application
version: '0.1' # just for humans. Semantic versioning is recommended
summary: A summary of your FastAPI application # 79 char long summary
description: |
This is fastapi project's description. You have a paragraph or two to tell the
most important story about it. Keep it under 100 words though,
we live in tweetspace and your description wants to look good in the
container registries out there.
platforms:
amd64:
extensions:
- fastapi-framework
```
File `app/main.py`
```
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
```
Also create an empty file named `app/__init__.py`
`ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=true rockcraft expand-extensions` fails with error:
```
ubuntu@paas-charm:~/delete/fastapi-hello-world$ ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=true rockcraft pack
*EXPERIMENTAL* extension 'fastapi-framework' enabled
Launching managed ubuntu 24.04 instance... :: Starting instance
*EXPERIMENTAL* extension 'fastapi-framework' enabled
/root/parts/fastapi-framework/install-app/install/app: No such file or directory
Detailed information: FileNotFoundError: filename: '/root/parts/fastapi-framework/install-app/install/app'
Failed to run rockcraft in instance
Full execution log: '/home/ubuntu/.local/state/rockcraft/log/rockcraft-20250530-175109.115787.log'
```
### Environment
```
ubuntu@paas-charm:~/delete/fastapi-hello-world$ sudo snap list rockcraft
Name Version Rev Tracking Publisher Notes
rockcraft 1.11.0 3313 latest/stable canonical✓ classic
```
It also fails with rockcraft `latest/edge` as of today
### rockcraft.yaml
```yaml
# This is the expanded rockcraft:
name: fastapi-hello-world
title: fastapi-hello-world
version: '0.1'
summary: A summary of your FastAPI application
description: |
This is fastapi project's description. You have a paragraph or two to tell the
most important story about it. Keep it under 100 words though,
we live in tweetspace and your description wants to look good in the
container registries out there.
base: ubuntu@24.04
platforms:
amd64:
build-on:
- amd64
build-for:
- amd64
parts:
fastapi-framework/dependencies:
plugin: python
stage-packages:
- python3-venv
source: .
python-packages:
- uvicorn
python-requirements:
- requirements.txt
fastapi-framework/install-app:
plugin: dump
source: .
organize:
app: app/app
stage:
- app/app
fastapi-framework/runtime:
plugin: nil
stage-packages:
- ca-certificates_data
run-user: _daemon_
services:
fastapi:
override: replace
command: /bin/python3 -m uvicorn app.main:app
startup: enabled
environment:
UVICORN_HOST: 0.0.0.0
user: _daemon_
working-dir: /app
```
### Relevant log output
```shell
:: 2025-05-30 17:51:38.801 execute action fastapi-framework/install-app:Action(part_name='fastapi-framework/install-app', step=Step.STAGE, action_type=ActionType.RUN, reason=None, project_vars=None, properties=ActionProperties(changed_files=None, changed_dirs=None))
:: 2025-05-30 17:51:39.328 /root/parts/fastapi-framework/install-app/install/app: No such file or directory
:: 2025-05-30 17:51:39.328 Detailed information: FileNotFoundError: filename: '/root/parts/fastapi-framework/install-app/install/app'
:: 2025-05-30 17:51:39.332 Traceback (most recent call last):
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/services/lifecycle.py", line 302, in run
:: 2025-05-30 17:51:39.332 aex.execute(action, stdout=stream, stderr=stream)
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 326, in execute
:: 2025-05-30 17:51:39.332 self._executor.execute(actions, stdout=stdout, stderr=stderr)
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 136, in execute
:: 2025-05-30 17:51:39.332 self._run_action(act, stdout=stdout, stderr=stderr)
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/executor.py", line 213, in _run_action
:: 2025-05-30 17:51:39.332 handler.run_action(action, stdout=stdout, stderr=stderr)
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 203, in run_action
:: 2025-05-30 17:51:39.332 state = handler(step_info, stdout=stdout, stderr=stderr)
:: 2025-05-30 17:51:39.332 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 408, in _run_stage
:: 2025-05-30 17:51:39.332 self._run_step(
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/part_handler.py", line 537, in _run_step
:: 2025-05-30 17:51:39.332 return step_handler.run_builtin()
:: 2025-05-30 17:51:39.332 ^^^^^^^^^^^^^^^^^^^^^^^^^^
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/step_handler.py", line 115, in run_builtin
:: 2025-05-30 17:51:39.332 return handler()
:: 2025-05-30 17:51:39.332 ^^^^^^^^^
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/step_handler.py", line 214, in _builtin_stage
:: 2025-05-30 17:51:39.332 files, dirs = migrate_files(
:: 2025-05-30 17:51:39.332 ^^^^^^^^^^^^^^
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/executor/migration.py", line 78, in migrate_files
:: 2025-05-30 17:51:39.332 file_utils.create_similar_directory(
:: 2025-05-30 17:51:39.332 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_parts/utils/file_utils.py", line 270, in create_similar_directory
:: 2025-05-30 17:51:39.332 stat = os.stat(source, follow_symlinks=False)
:: 2025-05-30 17:51:39.332 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:: 2025-05-30 17:51:39.332 FileNotFoundError: [Errno 2] No such file or directory: '/root/parts/fastapi-framework/install-app/install/app'
2025-05-30 17:51:39.795 Executing in container: lxc --project rockcraft exec local:rockcraft-fastapi-hello-world-amd64-7078398 -- env CRAFT_MANAGED_MODE=1 ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=true DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true DEBIAN_PRIORITY=critical test -f /tmp/rockcraft-pack.yaml
2025-05-30 17:51:40.063 Could not find state file /tmp/rockcraft-pack.yaml in instance.
2025-05-30 17:51:40.064 Executing on host: lxc --project rockcraft config device show local:rockcraft-fastapi-hello-world-amd64-7078398
2025-05-30 17:51:40.126 Executing on host: lxc --project rockcraft config device remove local:rockcraft-fastapi-hello-world-amd64-7078398 disk-/root/project
2025-05-30 17:51:40.217 Executing on host: lxc --project rockcraft stop local:rockcraft-fastapi-hello-world-amd64-7078398
2025-05-30 17:51:44.200 Executing on host: lxc --project rockcraft list local: --format=yaml
2025-05-30 17:51:44.336 Executing on host: lxc --project rockcraft list local: --format=yaml
2025-05-30 17:51:44.494 Failed to run rockcraft in instance
2025-05-30 17:51:44.495 Traceback (most recent call last):
2025-05-30 17:51:44.495 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/services/provider.py", line 448, in run_managed
2025-05-30 17:51:44.495 instance.execute_run( # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
2025-05-30 17:51:44.495 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_providers/lxd/lxd_instance.py", line 254, in execute_run
2025-05-30 17:51:44.495 return self.lxc.exec(
2025-05-30 17:51:44.495 ^^^^^^^^^^^^^^
2025-05-30 17:51:44.495 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_providers/lxd/lxc.py", line 390, in exec
2025-05-30 17:51:44.495 return runner(final_cmd, timeout=timeout, check=check, **kwargs)
2025-05-30 17:51:44.495 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-05-30 17:51:44.495 File "/snap/rockcraft/current/usr/lib/python3.12/subprocess.py", line 571, in run
2025-05-30 17:51:44.495 raise CalledProcessError(retcode, process.args,
2025-05-30 17:51:44.495 subprocess.CalledProcessError: Command '['lxc', '--project', 'rockcraft', 'exec', 'local:rockcraft-fastapi-hello-world-amd64-7078398', '--cwd', '/root/project', '--', 'env', 'CRAFT_MANAGED_MODE=1', 'ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS=true', 'DEBIAN_FRONTEND=noninteractive', 'DEBCONF_NONINTERACTIVE_SEEN=true', 'DEBIAN_PRIORITY=critical', 'CRAFT_PLATFORM=amd64', 'CRAFT_VERBOSITY_LEVEL=BRIEF', 'rockcraft', 'pack']' returned non-zero exit status 1.
2025-05-30 17:51:44.495
2025-05-30 17:51:44.495 The above exception was the direct cause of the following exception:
2025-05-30 17:51:44.495 Traceback (most recent call last):
2025-05-30 17:51:44.495 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/application.py", line 615, in run
2025-05-30 17:51:44.495 return_code = self._run_inner()
2025-05-30 17:51:44.496 ^^^^^^^^^^^^^^^^^
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/application.py", line 594, in _run_inner
2025-05-30 17:51:44.496 return_code = dispatcher.run() or os.EX_OK
2025-05-30 17:51:44.496 ^^^^^^^^^^^^^^^^
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_cli/dispatcher.py", line 528, in run
2025-05-30 17:51:44.496 return self._loaded_command.run(self._parsed_command_args)
2025-05-30 17:51:44.496 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/commands/base.py", line 199, in run
2025-05-30 17:51:44.496 result = self._run(parsed_args, **kwargs) or result
2025-05-30 17:51:44.496 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 433, in _run
2025-05-30 17:51:44.496 return super()._run(parsed_args=parsed_args, step_name=step_name)
2025-05-30 17:51:44.496 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 181, in _run
2025-05-30 17:51:44.496 self._run_manager_for_build_plan(fetch_service_policy)
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/commands/lifecycle.py", line 90, in _run_manager_for_build_plan
2025-05-30 17:51:44.496 provider.run_managed(build, bool(fetch_service_policy))
2025-05-30 17:51:44.496 File "/snap/rockcraft/3313/lib/python3.12/site-packages/craft_application/services/provider.py", line 455, in run_managed
2025-05-30 17:51:44.496 raise craft_providers.ProviderError(
2025-05-30 17:51:44.496 craft_providers.errors.ProviderError: Failed to run rockcraft in instance
2025-05-30 17:51:44.496 Full execution log: '/home/ubuntu/.local/state/rockcraft/log/rockcraft-20250530-175109.115787.log'
```
Evaluation history
| Date | Model | Scores | Action | Summary |
|---|---|---|---|---|
| ~deepseek/deepseek-pro-latest |
Impact:
45
Quick Win:
13
Complexity:
65
Confidence:
75
Actionability:
80
|
needs triage | fastapi-framework extension fails to pack when app code is in app/ directory; generated organize app: app/app causes FileNotFoundError in craft-parts. No maintainer response; root cause tracked in craft-parts#1460. | |
| qwen/qwen3.6-35b-a3b |
Impact:
70
Quick Win:
34
Complexity:
40
Confidence:
85
Actionability:
80
|
keep open | organize mapping {app: app/app} fails when app is a directory; blocked by craft-parts#1460 which remains unfixed. | |
| qwen/qwen3.8-27b |
Impact:
50
Quick Win:
22
Staleness:
25
Complexity:
55
Confidence:
75
Support Request:
5
|
keep open | fastapi-framework extension generates organize mapping 'app: app/app' when app code is in an app/ directory, causing FileNotFoundError during pack. Still present in current code; related craft-parts#1460 is open. Recently acknowledged by contributor wanting to work on it. | |
| qwen/qwen3.6-35b-a3b |
Staleness:
65
Complexity:
45
Confidence:
85
Support Request:
10
|
needs triage | Rockcraft fastapi-framework extension fails with FileNotFoundError when organizing app directory to app/app. Issue is unlabelled, unassigned, and awaiting maintainer review despite a recent contributor offer to fix it. | |
| qwen3.6-35b-a3b-mtp-q6 |
Staleness:
65
Complexity:
55
Confidence:
90
Support Request:
10
|
needs triage | Rockcraft fastapi-framework extension fails during packaging when organizing files into app/app. Well-reproduced bug with clear logs, awaiting maintainer triage despite recent volunteer interest. | |
| qwen3.6-35b-a3b-mtp-q6 |
Staleness:
60
Complexity:
40
Confidence:
85
Support Request:
10
|
needs triage | Bug in rockcraft fastapi-framework extension where organize directive fails with FileNotFoundError when source files are nested in a subdirectory. Recently volunteered by an external contributor. |
Update history
No update history recorded yet.
Related work
-
Duplicate Of:
canonical/craft-parts#1460
(confidence 85%)
Same underlying organize directory mapping bug; rockcraft's fastapi extension generates the app: app/app mapping that triggers it.
Related issues
No related issues found above the similarity threshold.