aws-samples / aws-samples/sample-autonomous-cloud-coding-agents
fix(agent): unrunnable pipeline.buildCommand kills the task pre-agent while a build timeout degrades gracefully
- Dominant language
- TypeScript
- Stars
- 143
- Forks
- 46
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 20
Description
### Component
Agent (Python runtime)
### Describe the bug
A `pipeline.buildCommand` whose executable does not exist in the agent container raises `FileNotFoundError` out of the pre-agent baseline build and **kills the task before the agent ever runs**. The surrounding code goes to considerable lengths to handle the analogous timeout case gracefully, so this looks like an oversight rather than a deliberate choice.
`agent/src/repo.py:457-473`:
```python
try:
result = run_cmd(build_argv, label="verify-build-pre", ..., timeout=BUILD_VERIFY_TIMEOUT_S, stream=True)
except subprocess.TimeoutExpired:
log("WARN", f"Initial build ({build_cmd_str}) did not finish within ... skipping baseline (not a regression)")
```
The comment above that block explains the reasoning for the timeout path at length — *"a timeout means 'no usable baseline', NOT 'the agent broke it', so we treat it as no-known-regression and let the run proceed"* — and notes that without the guard the task would "crash the whole task BEFORE the agent ever ran, so the issue got no PR and sat in Backlog — indistinguishable from a real failure."
A missing binary produces exactly that outcome, because only `TimeoutExpired` is caught.
### Expected behavior
An unrunnable build command should be treated the same way as a timeout: log a warning, record "no usable baseline", and let the agent run. The misconfiguration should be surfaced on the PR (and ideally as an inert-gate note), not converted into a task failure.
### Current behavior
The task dies during hydration with `build_passed=null` and no PR. Observed on task `01KZS2MS1BG7TDXHR7CDNMYM0A`:
```
status = FAILED
build_passed = null
error_message = FileNotFoundError: [Errno 2] No such file or directory: 'pytest'
```
Total time to failure: ~20 seconds. The agent never started, so a single typo in a blueprint's `buildCommand` bricks every task against that repo until someone redeploys.
### Reproduction steps
1. Onboard a repo with a `pipeline.buildCommand` naming a binary not present in the agent image, e.g. `buildCommand: 'pytest tests/unit/'` (the agent container's `PATH` leads with `/app/.venv/bin`, built `uv sync --frozen --no-dev` per `agent/Dockerfile:104`, so there is no `pytest`).
2. Submit any coding task against that repo.
3. Task fails in ~20s at hydration with the `FileNotFoundError` above; no PR, no agent turns.
### Possible solution
Catch `FileNotFoundError` (and likely `PermissionError`/`NotADirectoryError`) alongside `subprocess.TimeoutExpired` in both the pre-agent baseline (`agent/src/repo.py:457`) and the post-agent gate (`agent/src/post_hooks.py:187`), mapping them onto the existing inert-gate path rather than a task failure — an unrunnable command verified nothing, which is the definition of inert already handled elsewhere in `pipeline.py:1435-1441`.
Arguably a misconfigured blueprint should also surface a distinct, non-retryable error classification so the operator knows to fix the blueprint rather than retry.
Contributor guide
Research direction
Start with the existing TimeoutExpired handling in agent/src/repo.py:457-473 and compare the post-agent gate in agent/src/post_hooks.py:187. Review the inert-gate behavior in pipeline.py:1435-1441, then verify that an unavailable build executable is logged as having no usable baseline, allows the agent to run, and is surfaced on the PR rather than failing the task.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100