Skip to content

Make git-remote-entire errors readable for users - #2802

Merged
Soph merged 3 commits into
mainfrom
remote-message
Oct 21, 2026
Merged

Soph merged 3 commits into
mainfrom
remote-message

Conversation

@pjbgf

@pjbgf pjbgf commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

https://entire.io/gh/entireio/cli/trails/1598

The helper printed its whole Go error chain after "fatal:". Users saw protocol steps (stateless-connect, info/refs, the advertisement fetch), replica failover details, dial errors and full node URLs. None of it says what went wrong or what to do next. The same 404 also read differently depending on the git protocol version.

Known failures now print one line about the cluster and the repository. The full chain still goes to the ENTIRE_DEBUG trace. The transport returns typed errors (HTTPStatusError, ErrNoNodeSucceeded), so the top level picks the message by type instead of matching strings.

Repository not found:

  before: fatal: stateless-connect v2 info/refs: repository not found:
          https://<node>/gh/o/r
  before: fatal: list git-upload-pack info/refs: fetch git-upload-pack
          advertisement: repository not found: https://<node>/gh/o/r
  after:  fatal: repository gh/o/r not found on <cluster>

No access (clone or push):

  before: fatal: list git-receive-pack info/refs: fetch
          git-receive-pack advertisement: server error (HTTP 403):
          permission denied
  after:  fatal: you do not have access to gh/o/r on <cluster>
          (permission denied)

Login rejected:

  before: fatal: stateless-connect v2 info/refs: authentication failed
          even after refreshing credentials - run 'entire login' if
          this persists
  after:  fatal: <cluster> rejected your login. Run `entire login`,
          then try again

Server error:

  before: fatal: stateless-connect v2 info/refs: server error
          (HTTP 503): db timeout
  after:  fatal: <cluster> could not handle the request
          (HTTP 503: db timeout). Try again later

Every replica unreachable:

  before: fatal: stateless-connect v2 info/refs: fetching info/refs
          after entry-domain redirect: all 2 attempted nodes failed,
          last error: Get "https://<node>/gh/o/r/info/refs?service=
          git-upload-pack": dial tcp <ip>: connect: connection refused
  after:  fatal: could not reach any server for gh/o/r on <cluster>.
          Check your connection and try again

Other noise removed:

  • The replica failover path no longer puts HTML error pages from load balancers into the error. The entry URL path already dropped them.
  • An unrecognised GIT_PROTOCOL version is now noted in the debug trace instead of printing a warning on stderr.
  • Ctrl-C prints "interrupted" instead of a wrapped context error.

Redact URLs:

  before: fatal: invalid URL "entire://alice:s3cret@host:bad/gh/o/r": parse "entire://alice:s3cret@host:bad/gh/o/r": invalid port ":bad" after host after:  fatal: invalid URL: invalid port ":bad" after host before: fatal: missing host in URL "entire://alice:s3cret@/x/o/r" after:  fatal: missing host in URL "entire://xxxxx:xxxxx@/x/o/r"

Unchanged on purpose: the push-too-large and low-disk messages still print exactly as before. The migrate plugin matches the push-too-large marker on git's stderr. Errors the helper does not recognise also still print in full, because then the chain is the only clue to the cause.


Note

Low Risk
Changes are mostly error presentation and error typing in the git remote helper; auth and transport behavior are preserved aside from clearer failover error precedence.

Overview
git-remote-entire now maps helper failures to short, actionable fatal: lines (cluster + repo, login hints, connectivity) via userMessage / statusMessage, while the full Go error chain is logged only under ENTIRE_DEBUG. Invalid or malformed URLs no longer echo userinfo; missing-host messages redact credentials in the displayed URL.

The remote transport exposes typed errors (HTTPStatusError, ErrNoNodeSucceeded, ErrUnreachable) so the helper can classify outcomes without parsing strings. Replica failover uses shared body parsing (HTML stripped from 5xx messages), and when cached replicas fail then the entry URL fails, the fallback status drives classification (e.g. entry 404 is not masked by a stale cached 503).

Minor UX: unrecognized GIT_PROTOCOL values are debug-logged instead of stderr warnings; Ctrl-C surfaces as interrupted. Push-too-large, low-disk, and request-policy errors stay verbatim for existing tooling.

Reviewed by Cursor Bugbot for commit a7f191d. Configure here.

@pjbgf
pjbgf requested a review from a team as a code owner October 16, 2026 16:57
Copilot AI balanced review requested due to automatic review settings October 16, 2026 16:57
@pjbgf

pjbgf commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@cursor review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Error classification can hide final server responses and misreport security-policy rejections as connectivity failures.

2 open findings
What changed in this PR

Makes git-remote-entire failures easier to understand while retaining detailed diagnostics in debug output.

Changes:

  • Adds typed transport errors and concise user-facing messages.
  • Redacts URL credentials and moves protocol warnings to debug output.
  • Adds error-formatting and failover regression tests.
File Description
internal/​remotehelper/​transport/​status_error_test.go Tests typed failures and HTML suppression.
internal/​remotehelper/​transport/​proxy.go Types exhausted-replica errors and filters response bodies.
internal/​remotehelper/​transport/​inforefs.go Introduces typed HTTP status errors.
cmd/​git-remote-entire/​main.go Formats failures, redacts credentials, and reduces stderr noise.
cmd/​git-remote-entire/​main_test.go Tests messages, redaction, and protocol defaults.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cmd/git-remote-entire/main.go Resolved
Comment thread cmd/git-remote-entire/main.go Resolved

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread cmd/git-remote-entire/main.go Resolved
@pjbgf

pjbgf commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit a7f191d. Configure here.

pjbgf added 3 commits October 19, 2026 19:16
The helper printed its whole Go error chain after "fatal:". Users saw
protocol steps (stateless-connect, info/refs, the advertisement fetch),
replica failover details, dial errors and full node URLs. None of it
says what went wrong or what to do next. The same 404 also read
differently depending on the git protocol version.

Known failures now print one line about the cluster and the
repository. The full chain still goes to the ENTIRE_DEBUG trace. The
transport returns typed errors (HTTPStatusError, ErrNoNodeSucceeded),
so the top level picks the message by type instead of matching
strings.

Repository not found:
  before: fatal: stateless-connect v2 info/refs: repository not found:
          https://<node>/gh/o/r
  before: fatal: list git-upload-pack info/refs: fetch git-upload-pack
          advertisement: repository not found: https://<node>/gh/o/r
  after:  fatal: repository gh/o/r not found on <cluster>

No access (clone or push):
  before: fatal: list git-receive-pack info/refs: fetch
          git-receive-pack advertisement: server error (HTTP 403):
          permission denied
  after:  fatal: you do not have access to gh/o/r on <cluster>
          (permission denied)

Login rejected:
  before: fatal: stateless-connect v2 info/refs: authentication failed
          even after refreshing credentials - run 'entire login' if
          this persists
  after:  fatal: <cluster> rejected your login. Run `entire login`,
          then try again

Server error:
  before: fatal: stateless-connect v2 info/refs: server error
          (HTTP 503): db timeout
  after:  fatal: <cluster> could not handle the request
          (HTTP 503: db timeout). Try again later

Every replica unreachable:
  before: fatal: stateless-connect v2 info/refs: fetching info/refs
          after entry-domain redirect: all 2 attempted nodes failed,
          last error: Get "https://<node>/gh/o/r/info/refs?service=
          git-upload-pack": dial tcp <ip>: connect: connection refused
  after:  fatal: could not reach any server for gh/o/r on <cluster>.
          Check your connection and try again

Other noise removed:
- The replica failover path no longer puts HTML error pages from load
  balancers into the error. The entry URL path already dropped them.
- An unrecognised GIT_PROTOCOL version is now noted in the debug trace
  instead of printing a warning on stderr.
- Ctrl-C prints "interrupted" instead of a wrapped context error.

Redact URLs:
  before: fatal: invalid URL "entire://alice:s3cret@host:bad/gh/o/r":
          parse "entire://alice:s3cret@host:bad/gh/o/r": invalid port
          ":bad" after host
  after:  fatal: invalid URL: invalid port ":bad" after host
  before: fatal: missing host in URL "entire://alice:s3cret@/x/o/r"
  after:  fatal: missing host in URL "entire://xxxxx:xxxxx@/x/o/r"

Unchanged on purpose: the push-too-large and low-disk messages still
print exactly as before. The migrate plugin matches the push-too-large
marker on git's stderr. Errors the helper does not recognise also
still print in full, because then the chain is the only clue to the
cause.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Paulo Gomes <paulo@entire.io>
Entire-Checkpoint: 01M52T8RSNNKEJRRS8T3MKBHMC
A cached replica's 503 no longer hides the entry URL's answer. When
both fail, only the fallback's error is wrapped, so a 404, 401 or 403
from the entry URL drives the message. The cached failure stays in the
text for the debug trace.

Request-policy rejections, such as an HTTPS-to-HTTP redirect, now
print in full instead of the connectivity hint. That holds even when
another node answered with a 5xx, because a refused unsafe hop is a
security diagnostic, not a server problem.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Paulo Gomes <paulo@entire.io>
Entire-Checkpoint: 01M536G4QVEB1ENBBN5S9FRYJ2
An unreachable entry domain now reads as a connectivity failure. Only
replica failover tagged its errors before, so a first clone against
an offline or mistyped cluster still printed the full chain. Transport
failures to send a request, and an empty or ineligible replica set,
now match transport.ErrUnreachable. Failures to build the request,
such as a credential error, are not tagged.

  before: fatal: stateless-connect v2 info/refs: fetching info/refs
          from entry domain: doing request: Get "https://<host>/...":
          dial tcp ...: connect: connection refused
  after:  fatal: could not reach any server for gh/o/r on <cluster>.
          Check your connection and try again

A 401 under ENTIRE_TOKEN names the token instead of suggesting
`entire login`, which cannot replace it.

  before: fatal: <cluster> rejected your login. Run `entire login`,
          then try again
  after:  fatal: <cluster> rejected ENTIRE_TOKEN

A 404 keeps the server's message in parentheses, as 401 and 403 do,
so anything actionable in the body still reaches the user.

HTTPErrorMessage is renamed to newHTTPStatusError, since it returns a
typed error and only the transport package calls it.

Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Paulo Gomes <paulo@entire.io>
Entire-Checkpoint: 01M537KV1PHTYG9MV15HTF1FRN
@Soph
Soph merged commit af0e086 into main Oct 21, 2026
19 checks passed
@Soph
Soph deleted the remote-message branch October 21, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants