Skip to content

Guide 08 of 9

Troubleshoot a run

The first thing to check for each common outcome, from an unknown program to a missing speed-up.

Plate 17 A leaking union opened up, its split washer lifted out for inspection, as a failed run is taken apart to find the cause.

First checks

First checks for common outcomes
Symptom Check
ImportError or AttributeError for a documented name An older Cuprum may be installed: pip and uv skip a pre-release unless it is named, so pin cuprum==0.2.0b2.
UnknownProgramError Register the exact program in the builder’s catalogue, or in the active scoped(catalogue=...), which sh.make now resolves.
ForbiddenProgramError Inspect the active scope and its parent’s allowlist; a builder can be made from a catalogue the scope does not allow.
TypeError while building a command The message names the problem: an unsupported value type, None, or a reserved execution option such as cwd=, which belongs on run_sync.
FileNotFoundError Confirm the executable’s path, or the PATH the child inherits; a replacement environment without PATH cannot resolve a bare name.
ExecutableResolutionError An executable-binding resolver failed or returned the wrong type; its own exception is chained as __cause__.
TimeoutExpired Set a deadline that fits the work, and look for slow or blocked work in the child.
ValueError naming a redirected stream Capture or echo with a redirected stream, one path for both streams, or a redirect with lines() or start() is contradictory; see the rejected combinations under Control output.
StdinSourceError The stdin producer failed or yielded something that is neither str nor bytes; its own exception is chained as __cause__.
RedactionError A redaction rule failed and nothing was exported unredacted. Check the rule the message names.
SignalAfterExitError The child has already exited; treat the recorded outcome as the command’s ending.
UnsupportedSignalError Use terminate() or kill(), which use the platform’s own signals.
ValueError from run_bytes() A byte-exact run refuses on_line; observe lines with sh.observe() instead, or run in text mode.
ValueError at spawn with OWN_GROUP Windows has no POSIX process groups; keep ProcessGroupPolicy.INHERIT there.
A non-zero exit_code Read the captured stderr and the tool’s documented exit codes.
No visible output Capture is silent by default: pass RunOutputOptions(echo=True), or read result.stdout.
No heartbeat Supply a positive idle_after; any output resets its clock.
Descendants outlive a timeout Opt in to process-group ownership on POSIX, so teardown signals the group the child leads.
No native speed-up The extension may be missing, or this operation may use the Python path.

Check the native extension

is_rust_available reports whether the native backend can be used. It returns False on a pure-Python install rather than raising, while other import failures still surface, so a broken installation stays visible.

rust_available.py Tested
import cuprum

assert isinstance(cuprum.is_rust_available(), bool)
Run 2026-10-19 against Cuprum 0.2.0b2 · Python 3.12 · Linux

Behaviour is the same with or without the extension. The Rust extension page covers backend selection and why a hop falls back to Python.