Skip to content

fix(auth): always show login URL so headless login can complete#420

Open
theFong wants to merge 1 commit into
mainfrom
fix/register-headless-login-url
Open

fix(auth): always show login URL so headless login can complete#420
theFong wants to merge 1 commit into
mainfrom
fix/register-headless-login-url

Conversation

@theFong

@theFong theFong commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

brev register (and any login flow) hangs and times out after 5 minutes on a headless machine (e.g. an SSH'd server):

Enter your email: alecf@nvidia.com
Waiting for login to complete in browser...
Error: no DISPLAY environment variable specified
failed.
...
timed out waiting for login

Root cause

On a machine with no display but xdg-open installed:

  1. hasBrowser() returned true — it only checked whether xdg-open existed, not whether a display was available.
  2. defaultAuthFunc called browser.OpenURL(url). xdg-open printed Error: no DISPLAY environment variable specified to stderr but exited 0, so OpenURL returned nil.
  3. The code took the success branch: printed "Waiting for login to complete in browser..." and returned — without ever printing the login URL.
  4. With no URL to visit, login could never complete, so polling ran its full 5-minute timeout and failed.

Fix

Follow the same pattern Claude Code's CLI uses: always attempt to open the browser best-effort, but always print the login URL as a fallback, so the user is never stranded regardless of environment.

  • defaultAuthFunc: attempt browser.OpenURL (ignore the result), then always showLoginURL.
  • showLoginURL: reframed as a fallback — Browser didn't open? Use the URL below to sign in:.
  • Discard the launcher's stderr (browser.Stderr = io.Discard) — pkg/browser pipes it to ours, which is what leaked the confusing no DISPLAY message.
  • This removes the need for any platform/display detection, so hasBrowser() is deleted (net −9 lines).

Note: brev register uses an in-memory device-login flow (it does not reuse ~/.brev credentials), so it always hits this path — this fix is what unblocks register on headless machines.

Testing

  • go build ./..., go vet ./pkg/auth/, go test ./pkg/auth/
  • Cross-built linux/arm64 and ran on a headless (no DISPLAY) arm64 box: login now prints the URL instead of hanging.

@theFong theFong requested a review from a team as a code owner July 2, 2026 06:57
On a machine with no display (e.g. an SSH'd server), login hung and
timed out after 5 minutes. hasBrowser() returned true because xdg-open
was installed, so browser.OpenURL was called; xdg-open printed "no
DISPLAY environment variable specified" to stderr but exited 0, so
OpenURL returned nil and the CLI printed "Waiting for login to complete
in browser..." without ever showing the login URL. With no URL to visit,
login could never complete.

Follow Claude Code's pattern: always attempt to open the browser
best-effort, but always print the login URL as a fallback so the user is
never stranded. Discard the launcher's stderr (pkg/browser pipes it to
ours) to suppress the confusing "no DISPLAY" noise. This removes the need
for platform/display detection, so hasBrowser() is deleted.
@theFong theFong force-pushed the fix/register-headless-login-url branch from 84e5b32 to 5e81f25 Compare July 2, 2026 15:00
@theFong theFong changed the title fix(auth): show login URL on headless machines so login can complete fix(auth): always show login URL so headless login can complete Jul 2, 2026
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.

2 participants