bug(finish): resolveForeignDefaultBranch swallows the real error — credential failures masquerade as 'forge API unreachable' #93

Closed
opened 2026-07-15 15:13:58 +00:00 by hexajon · 0 comments
hexajon commented 2026-07-15 15:13:58 +00:00 (Migrated from codeberg.org)

Observed 2026-07-15 while landing ADR 0027 (PR #92) through the sanctioned foreign-finish flow.

resolveForeignDefaultBranch (internal/service/workflow/helpers.go:439) swallows every underlying error: finishClientFn failure, GetCurrentRepo failure, and unmarshal failure all collapse to the bare ("", nil, "") sentinel, and the caller replaces them with foreignDefaultBranchUnresolvedError — "the forge API was unreachable, or the target repository has no default branch yet (never pushed)".

The actual failure was neither: GetConfigForDir failed credential resolution for the target dir (the companion token-source issue), which produces the good error — "no credentials for codeberg.org — run madtea auth login (from a repo on that forge…)" — naming the host and the remedy. That message was discarded, and the substitute sent the operator and agent chasing network reachability and repo-emptiness, both false. Diagnosing required reading the source; the refusal violated the spirit of ADR 0026 (refusals teach the actual next step) even though no hook chain is involved.

Fix: thread the underlying error out of resolveForeignDefaultBranch (return it, or at minimum wrap it into foreignDefaultBranchUnresolvedError's text) so a credential-resolution failure surfaces as itself. The "unreachable or never pushed" wording should only appear when the client was built successfully and the GET actually failed/returned empty.

Acceptance: a foreign finish whose target dir has no resolvable credentials errors with the "no credentials for " message (host + remedy named), not the unreachable/never-pushed text; a genuine network failure still reports as such.

Observed 2026-07-15 while landing ADR 0027 (PR #92) through the sanctioned foreign-finish flow. `resolveForeignDefaultBranch` (internal/service/workflow/helpers.go:439) swallows every underlying error: `finishClientFn` failure, `GetCurrentRepo` failure, and unmarshal failure all collapse to the bare `("", nil, "")` sentinel, and the caller replaces them with `foreignDefaultBranchUnresolvedError` — "the forge API was unreachable, or the target repository has no default branch yet (never pushed)". The actual failure was neither: `GetConfigForDir` failed credential resolution for the target dir (the companion token-source issue), which produces the *good* error — "no credentials for codeberg.org — run madtea auth login (from a repo on that forge…)" — naming the host and the remedy. That message was discarded, and the substitute sent the operator and agent chasing network reachability and repo-emptiness, both false. Diagnosing required reading the source; the refusal violated the spirit of ADR 0026 (refusals teach the actual next step) even though no hook chain is involved. Fix: thread the underlying error out of `resolveForeignDefaultBranch` (return it, or at minimum wrap it into `foreignDefaultBranchUnresolvedError`'s text) so a credential-resolution failure surfaces as itself. The "unreachable or never pushed" wording should only appear when the client was built successfully and the GET actually failed/returned empty. Acceptance: a foreign finish whose target dir has no resolvable credentials errors with the "no credentials for <host>" message (host + remedy named), not the unreachable/never-pushed text; a genuine network failure still reports as such.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#93
No description provided.