Skip to content

fix(spawn): map invalid branch name to 400 instead of opaque 500#213

Open
codebanditssss wants to merge 1 commit into
mainfrom
fix/spawn-invalid-branch-400
Open

fix(spawn): map invalid branch name to 400 instead of opaque 500#213
codebanditssss wants to merge 1 commit into
mainfrom
fix/spawn-invalid-branch-400

Conversation

@codebanditssss

Copy link
Copy Markdown
Collaborator

Closes #212.

Problem

ao spawn --branch "<invalid name>" returned an opaque INTERNAL_ERROR 500. gitworktree.validateBranch wrapped the git check-ref-format failure in an untyped error, so toAPIError fell through to default and the envelope collapsed it to 500.

This is the residual of #152 Bug 3: that RCA typed the not-fetched and checked-out-elsewhere branch errors (now 400/409), but the invalid-format case — the first check in validateBranch — never got a sentinel.

Change

  • Add ports.ErrWorkspaceBranchInvalid, aliased in the gitworktree adapter alongside the existing two.
  • Wrap it in validateBranch (keeps git's own message for the user).
  • Map it in toAPIErrorapierr.Invalid("INVALID_BRANCH", ...) (400).

Test

  • TestCreateRejectsInvalidBranchName (gitworktree): Create with a bad branch returns ErrWorkspaceBranchInvalid and stops before any further git call.
  • TestToAPIErrorMapsWorkspaceBranchSentinels: adds the INVALID_BRANCH mapping case.
  • go build ./... and full go test ./... pass.
  • End-to-end against a live daemon: --branch "bad branch name!!" now returns INVALID_BRANCH (exit 1) with git's reason, instead of Internal server error.

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes the missing typed sentinel for invalid git branch names so that ao spawn --branch "<invalid>" returns a 400 INVALID_BRANCH response instead of an opaque 500. The change is the last piece of the #152 Bug 3 RCA, completing the trilogy of typed workspace-branch errors.

  • Adds ErrWorkspaceBranchInvalid to ports/outbound.go, aliases it in the gitworktree adapter, and wraps it in validateBranch using dual-%w (valid since Go 1.20) so both the sentinel and git's own message are preserved in the error chain.
  • Maps the new sentinel in toAPIErrorapierr.Invalid("INVALID_BRANCH", ...) (400) and covers it with a targeted unit test that asserts no git call beyond check-ref-format is made.

Confidence Score: 5/5

Safe to merge; the change is a narrow, well-tested addition of a new error sentinel and its mapping — no existing behavior is altered.

The diff touches only the error-classification path: a new sentinel, one wrapping site, one switch case, and matching tests. The dual-%w format string is valid on Go 1.20+ (the module declares 1.25), errors.Is traversal is unaffected, and no existing mappings are disturbed.

No files require special attention.

Important Files Changed

Filename Overview
backend/internal/ports/outbound.go Adds ErrWorkspaceBranchInvalid sentinel with a clear doc comment, placed logically next to the other two workspace branch sentinels.
backend/internal/adapters/workspace/gitworktree/workspace.go Adds ErrBranchInvalid alias and rewraps validateBranch using dual-%w (Go 1.20+) so the sentinel is errors.Is-matchable; doc-comment on the var block still names only the original two aliases.
backend/internal/service/session/service.go Maps ErrWorkspaceBranchInvalid to apierr.Invalid with code INVALID_BRANCH; minor inconsistency with the BRANCH_* prefix convention used by the other two branch codes.
backend/internal/adapters/workspace/gitworktree/workspace_test.go New test confirms validateBranch fires first and returns ErrWorkspaceBranchInvalid, and that no further git calls are made; t.Fatalf is safe here because the stub is called synchronously on the test goroutine.
backend/internal/service/session/service_test.go Extends TestToAPIErrorMapsWorkspaceBranchSentinels with the INVALID_BRANCH case; wrapping format in the test fixture mirrors real production wrapping.

Sequence Diagram

sequenceDiagram
    participant CLI as ao CLI
    participant Svc as session.Service
    participant WS as gitworktree.Workspace
    participant Git as git check-ref-format

    CLI->>Svc: "Spawn(branch="bad branch!!")"
    Svc->>WS: Create(WorkspaceConfig)
    WS->>Git: check-ref-format --branch "bad branch!!"
    Git-->>WS: exit 1 (fatal: not a valid branch name)
    WS-->>Svc: fmt.Errorf("%w: %q (%w)", ErrBranchInvalid, branch, gitErr)
    Note over Svc: toAPIError detects ErrWorkspaceBranchInvalid
    Svc-->>CLI: 400 INVALID_BRANCH (git's reason included)
Loading

Reviews (2): Last reviewed commit: "fix(spawn): map invalid branch name to 4..." | Re-trigger Greptile

validateBranch returned an untyped error for a name rejected by
git check-ref-format, so toAPIError fell through to INTERNAL_ERROR 500.

Add a ports.ErrWorkspaceBranchInvalid sentinel (mirroring the not-fetched /
checked-out-elsewhere ones), wrap it in validateBranch, and map it to
INVALID_BRANCH (400). Completes the residual of #152 Bug 3, which typed the
not-fetched and checked-out-elsewhere cases but left the invalid-format case
collapsing to 500.

Closes #212
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ao spawn --branch <invalid format> returns opaque 500 instead of 400 (residual of #152 Bug 3)

1 participant