Catch `FileNotFound` for all `subprocess.run()` calls
Metadata
Current evaluation
Enhancement to catch FileNotFoundError from subprocess.run() calls across craft-providers and raise ProviderError for better user-facing error messages. Still open.
Suggested action: keep open
Reason: The issue requests a valid enhancement to improve error handling when provider binaries (like lxc or multipass) are missing. Currently, subprocess.run() calls in lxc.py, multipass.py, and installers raise unhandled FileNotFoundError. The fix requires wrapping these calls or centralizing them to catch the exception and raise ProviderError. It's clearly scoped with a reproducer and example traceback.
Evaluated by: mr-cal-bot
Impact:
70
Quick Win:
28
Complexity:
50
Confidence:
85
Actionability:
80
Issue body
### What needs to get done
Catch `FileNotFound` for all `subprocess.run()` calls and raise a `ProviderError`.
### Why it needs to get done
If the executable is not available, `FileNotFound` bubbles up as an internal error via craft-application.
### Example
```
(testcraft_venv) root@u2204-parts-dev:/opt/testcraft/examples/ruff# testcraft pack
testcraft internal error: FileNotFoundError(2, 'No such file or directory')
Full execution log: '/root/.local/state/testcraft/log/testcraft-20240620-161753.039218.log'
```
```
2024-06-20 16:17:53.076 Executing on host: lxc remote list --format=yaml
2024-06-20 16:17:53.077 testcraft internal error: FileNotFoundError(2, 'No such file or directory')
2024-06-20 16:17:53.080 Traceback (most recent call last):
2024-06-20 16:17:53.080 File .../craft_application/application.py", line 536, in run
2024-06-20 16:17:53.080 self.run_managed(platform, build_for)
2024-06-20 16:17:53.080 File .../craft_application/application.py", line 361, in run_managed
2024-06-20 16:17:53.080 with self.services.provider.instance(
2024-06-20 16:17:53.080 File "/usr/lib/python3.10/contextlib.py", line 135, in __enter__
2024-06-20 16:17:53.080 return next(self.gen)
2024-06-20 16:17:53.080 File .../craft_application/services/provider.py", line 120, in instance
2024-06-20 16:17:53.080 with provider.launched_environment(
2024-06-20 16:17:53.080 File "/usr/lib/python3.10/contextlib.py", line 135, in __enter__
2024-06-20 16:17:53.080 return next(self.gen)
2024-06-20 16:17:53.080 File "/root/testcraft_venv/lib/python3.10/site-packages/craft_providers/lxd/lxd_provider.py", line 137, in launched_environment
2024-06-20 16:17:53.080 image.add_remote(lxc=self.lxc)
2024-06-20 16:17:53.080 File "/root/testcraft_venv/lib/python3.10/site-packages/craft_providers/lxd/remotes.py", line 97, in add_remote
2024-06-20 16:17:53.080 if self.remote_name in lxc.remote_list():
2024-06-20 16:17:53.080 File "/root/testcraft_venv/lib/python3.10/site-packages/craft_providers/lxd/lxc.py", line 1001, in remote_list
2024-06-20 16:17:53.080 proc = self._run_lxc(command, capture_output=True)
2024-06-20 16:17:53.080 File "/root/testcraft_venv/lib/python3.10/site-packages/craft_providers/lxd/lxc.py", line 104, in _run_lxc
2024-06-20 16:17:53.080 return subprocess.run(lxc_cmd, check=check, stdin=stdin.value, **kwargs)
2024-06-20 16:17:53.080 File "/usr/lib/python3.10/subprocess.py", line 503, in run
2024-06-20 16:17:53.080 with Popen(*popenargs, **kwargs) as process:
2024-06-20 16:17:53.080 File "/usr/lib/python3.10/subprocess.py", line 971, in __init__
2024-06-20 16:17:53.080 self._execute_child(args, executable, preexec_fn, close_fds,
2024-06-20 16:17:53.080 File "/usr/lib/python3.10/subprocess.py", line 1863, in _execute_child
2024-06-20 16:17:53.080 raise child_exception_type(errno_num, err_msg, err_filename)
2024-06-20 16:17:53.080 FileNotFoundError: [Errno 2] No such file or directory: 'lxc'
```
Evaluation history
| Date | Model | Scores | Action | Summary |
|---|---|---|---|---|
| qwen/qwen3.6-35b-a3b |
Impact:
70
Quick Win:
28
Complexity:
50
Confidence:
85
Actionability:
80
|
keep open | Enhancement to catch FileNotFoundError from subprocess.run() calls across craft-providers and raise ProviderError for better user-facing error messages. Still open. | |
| stealth/space-bunny-alpha |
Impact:
45
Quick Win:
13
Complexity:
60
Confidence:
91
Actionability:
72
|
keep open | Missing provider executables still escape as FileNotFoundError instead of ProviderError; direct subprocess.run call sites remain, so the cross-cutting enhancement is unresolved. | |
| stealth/space-bunny-alpha |
Impact:
47
Quick Win:
18
Complexity:
54
Confidence:
95
Actionability:
85
|
keep open | Missing host executables such as lxc still surface as FileNotFoundError rather than ProviderError; this maintainer-labeled enhancement remains unresolved. | |
| qwen3.6-35b-a3b-mtp-q6 |
Impact:
50
Quick Win:
35
Staleness:
80
Complexity:
30
Confidence:
75
Support Request:
10
|
keep open | Enhancement to catch FileNotFoundError from subprocess.run calls in LXC and Multipass wrappers, raising ProviderError instead. Unaddressed for over two years. | |
| qwen/qwen3.6-35b-a3b |
Staleness:
85
Complexity:
20
Confidence:
90
Support Request:
5
|
needs triage | Enhancement to catch FileNotFoundError from subprocess.run() calls and raise ProviderError instead of bubbling up as an internal error. Currently untriaged with only an automated Jira sync comment. | |
| qwen3.6-35b-a3b-mtp-q6 |
Staleness:
85
Complexity:
20
Confidence:
85
Support Request:
0
|
keep open | Enhancement to catch FileNotFoundError in subprocess.run calls and raise ProviderError instead of bubbling up as an internal error. Currently inactive with no maintainer follow-up since June 2024. |
Update history
No update history recorded yet.
Related issues
No related issues found above the similarity threshold.