Summary
Any basecamp command that touches stored credentials (auth login, auth status, doctor, projects list, etc.) hangs forever, with no error and no timeout, on a Linux desktop where a D-Bus session bus and gnome-keyring-daemon are both present and working normally. Root cause: the github.com/zalando/go-keyring Secret Service (D-Bus) backend's low-level D-Bus auth handshake never completes, and nothing times it out.
Environment
basecamp version 0.11.0
- Linux (Omarchy/Hyprland desktop),
gnome-keyring-daemon running (pkcs11,secrets components), registered on the session bus as org.freedesktop.secrets / org.gnome.keyring
dbus-send --session ... org.freedesktop.DBus.ListNames works fine and returns immediately — the bus itself and other D-Bus clients are healthy
- System clock is NTP-synced
Reproduction
$ basecamp auth status --json
# hangs indefinitely, no output, no timeout
Same hang on basecamp doctor --json, basecamp auth login (both default browser flow and --device-code/--remote), and any data command like basecamp projects list once credentials need to be read. --version and --help return instantly (they don't touch the credential store), which is what pointed us at credential storage rather than the network as the culprit — a plain curl -v https://3.basecamp.com / https://launchpad.37signals.com completes in well under 200ms the whole time this is hanging, ruling out a network/proxy issue.
Diagnosis
Sent SIGQUIT to the hung process to get a goroutine dump (Go's default behavior — dumps all stacks and exits). The main goroutine is parked here even during a device-code login after the OAuth exchange has already succeeded (Authorization.GetInfo and People.Me both completed):
goroutine 1 [chan receive]:
...
github.com/zalando/go-keyring.secretServiceProvider.Set(...)
github.com/zalando/go-keyring@.../secret_service/...
...
with a companion goroutine permanently blocked reading from the D-Bus unix socket during the SASL/EXTERNAL auth handshake:
github.com/godbus/dbus/v5.(*Conn).inWorker(...)
github.com/godbus/dbus/v5@v5.2.2/conn.go:390
net.(*UnixConn).ReadMsgUnix(...)
internal/poll.(*FD).ReadMsg(...)
So: the CLI opens its own new D-Bus connection (rather than reusing/sharing the session bus connection other tools use) to talk to the Secret Service, and on this machine that connection's auth handshake never resolves — even though the exact same bus is trivially reachable via dbus-send in another process at the same moment. Whatever the cause on the D-Bus/gnome-keyring side, the CLI has no timeout around this call, so it wedges the whole process (and, transitively, auth login, auth status, and doctor, since they all go through the same credential store).
Confirmed workaround
Setting BASECAMP_NO_KEYRING=1 (an env var already compiled into the binary, presumably intended for exactly this) skips the keyring path entirely and every command returns instantly:
$ BASECAMP_NO_KEYRING=1 basecamp auth status --json
{"ok":true,"data":{"authenticated":true,...}} # instant
This isn't documented anywhere in --help output (auth --help, config --help, top-level --help), so it took a strings pass over the binary to discover. Also worth noting: basecamp already has a message for the explicit-error keyring-unavailable case ("system keyring unavailable (%v), credentials stored in plaintext at %s"), it just doesn't reach that fallback when the keyring call hangs instead of erroring.
Suggested fixes
- Wrap the keyring Set/Get calls in a bounded context/timeout (a few seconds is plenty) and fall back to the existing plaintext-storage path on timeout, the same as the existing "keyring unavailable" error path.
- Document
BASECAMP_NO_KEYRING in --help output and/or basecamp doctor, so people hitting this don't have to reverse-engineer it.
- Possibly related to the gnome-keyring Secret Service/D-Bus issues already tracked in
basecamp/hey-cli#352 and basecamp/hey-cli#453 (see also this comment diagnosing the OpenSession/GVariant assertion chain on GNOME Keyring 50.0 on Omarchy) — different symptom (daemon aborts vs. a client-side hang with no timeout), same subsystem (zalando/go-keyring + gnome-keyring D-Bus Secret Service on Omarchy/Hyprland), so may share a root cause worth checking together.
Happy to provide the full goroutine dump or test further if useful.
Summary
Any
basecampcommand that touches stored credentials (auth login,auth status,doctor,projects list, etc.) hangs forever, with no error and no timeout, on a Linux desktop where a D-Bus session bus andgnome-keyring-daemonare both present and working normally. Root cause: thegithub.com/zalando/go-keyringSecret Service (D-Bus) backend's low-level D-Bus auth handshake never completes, and nothing times it out.Environment
basecamp version 0.11.0gnome-keyring-daemonrunning (pkcs11,secretscomponents), registered on the session bus asorg.freedesktop.secrets/org.gnome.keyringdbus-send --session ... org.freedesktop.DBus.ListNamesworks fine and returns immediately — the bus itself and other D-Bus clients are healthyReproduction
Same hang on
basecamp doctor --json,basecamp auth login(both default browser flow and--device-code/--remote), and any data command likebasecamp projects listonce credentials need to be read.--versionand--helpreturn instantly (they don't touch the credential store), which is what pointed us at credential storage rather than the network as the culprit — a plaincurl -v https://3.basecamp.com/https://launchpad.37signals.comcompletes in well under 200ms the whole time this is hanging, ruling out a network/proxy issue.Diagnosis
Sent
SIGQUITto the hung process to get a goroutine dump (Go's default behavior — dumps all stacks and exits). The main goroutine is parked here even during a device-code login after the OAuth exchange has already succeeded (Authorization.GetInfoandPeople.Meboth completed):with a companion goroutine permanently blocked reading from the D-Bus unix socket during the SASL/
EXTERNALauth handshake:So: the CLI opens its own new D-Bus connection (rather than reusing/sharing the session bus connection other tools use) to talk to the Secret Service, and on this machine that connection's auth handshake never resolves — even though the exact same bus is trivially reachable via
dbus-sendin another process at the same moment. Whatever the cause on the D-Bus/gnome-keyring side, the CLI has no timeout around this call, so it wedges the whole process (and, transitively,auth login,auth status, anddoctor, since they all go through the same credential store).Confirmed workaround
Setting
BASECAMP_NO_KEYRING=1(an env var already compiled into the binary, presumably intended for exactly this) skips the keyring path entirely and every command returns instantly:This isn't documented anywhere in
--helpoutput (auth --help,config --help, top-level--help), so it took astringspass over the binary to discover. Also worth noting:basecampalready has a message for the explicit-error keyring-unavailable case ("system keyring unavailable (%v), credentials stored in plaintext at %s"), it just doesn't reach that fallback when the keyring call hangs instead of erroring.Suggested fixes
BASECAMP_NO_KEYRINGin--helpoutput and/orbasecamp doctor, so people hitting this don't have to reverse-engineer it.basecamp/hey-cli#352andbasecamp/hey-cli#453(see also this comment diagnosing the OpenSession/GVariant assertion chain on GNOME Keyring 50.0 on Omarchy) — different symptom (daemon aborts vs. a client-side hang with no timeout), same subsystem (zalando/go-keyring+ gnome-keyring D-Bus Secret Service on Omarchy/Hyprland), so may share a root cause worth checking together.Happy to provide the full goroutine dump or test further if useful.