Bug
ao spawn --harness <unknown> (a typo'd or unregistered agent) returns an opaque Internal server error (INTERNAL_ERROR) 500 instead of a 400 validation error.
Analyzed against: 3e64c15 | Confidence: High
Reproduction
ao spawn --project <p> --harness bogus-agent --prompt x
# → Internal server error (INTERNAL_ERROR)
Root Cause
In backend/internal/session_manager/manager.go Spawn, the harness is only resolved at m.agents.Agent(cfg.Harness) after CreateSession + workspace.Create + provisioning. On an unknown harness that lookup returns ok=false and the code returns a plain fmt.Errorf("...no agent adapter for harness %q", ...) — not a sentinel — so toAPIError (backend/internal/service/session/service.go) hits its default branch and WriteError collapses it to INTERNAL_ERROR 500.
Worse, because the failure happens late, it also creates a seed row, builds and tears down a worktree, and parks a terminated orphan row for a spawn that could never launch — the same "create row before validating preconditions" pattern called out in #152.
This is the unknown-harness-name sibling of #152 Bug 6 (which fixed unknown binary on PATH → AGENT_BINARY_NOT_FOUND); that fix does not cover a harness with no registered adapter at all.
Fix
Validate the harness against the registry before any durable state is created (right after effectiveHarness), returning a typed ErrUnknownHarness mapped to apierr.Invalid("UNKNOWN_HARNESS", ...). This makes a typo'd --harness a clean 400 and avoids the orphan row + wasted worktree.
Impact
A common user typo (--harness codx) produces a confusing 500 and litters the session list with a terminated orphan. Labels: bug, priority: medium.
Bug
ao spawn --harness <unknown>(a typo'd or unregistered agent) returns an opaqueInternal server error (INTERNAL_ERROR)500 instead of a 400 validation error.Analyzed against:
3e64c15| Confidence: HighReproduction
Root Cause
In
backend/internal/session_manager/manager.goSpawn, the harness is only resolved atm.agents.Agent(cfg.Harness)afterCreateSession+workspace.Create+ provisioning. On an unknown harness that lookup returnsok=falseand the code returns a plainfmt.Errorf("...no agent adapter for harness %q", ...)— not a sentinel — sotoAPIError(backend/internal/service/session/service.go) hits itsdefaultbranch andWriteErrorcollapses it toINTERNAL_ERROR500.Worse, because the failure happens late, it also creates a seed row, builds and tears down a worktree, and parks a terminated orphan row for a spawn that could never launch — the same "create row before validating preconditions" pattern called out in #152.
This is the unknown-harness-name sibling of #152 Bug 6 (which fixed unknown binary on PATH →
AGENT_BINARY_NOT_FOUND); that fix does not cover a harness with no registered adapter at all.Fix
Validate the harness against the registry before any durable state is created (right after
effectiveHarness), returning a typedErrUnknownHarnessmapped toapierr.Invalid("UNKNOWN_HARNESS", ...). This makes a typo'd--harnessa clean 400 and avoids the orphan row + wasted worktree.Impact
A common user typo (
--harness codx) produces a confusing 500 and litters the session list with a terminated orphan. Labels:bug,priority: medium.