fix(cli): error when CODER_SESSION_TOKEN env var is set during login (#22879)

_Disclaimer: created with Opus 4.6 and Coder Agents._

## Problem

When `CODER_SESSION_TOKEN` is set as an environment variable with an
invalid value, `coder login` fails with a confusing error:

```
error: Trace=[create api key: ]
You are signed out or your session has expired. Please sign in again to continue.
Suggestion: Try logging in using 'coder login'.
```

The suggestion to run `coder login` is what the user just did, making it
circular and unhelpful.

## Root cause

The `--token` flag is mapped to `CODER_SESSION_TOKEN` via serpent. When
the env var is set, `coder login` picks it up as the session token and
tries to use it to create a new API key, which fails because the token
is invalid. Even if login were to succeed and write a new token to disk,
subsequent commands would still use the env var (which takes precedence
over the on-disk token), so the user would remain stuck.

## Fix

Before attempting login, check if `CODER_SESSION_TOKEN` is set in the
environment. If so, return a clear error telling the user to unset it:

```
the environment variable CODER_SESSION_TOKEN is set, which takes precedence
over the session token stored on disk. Please unset it and try again.

    unset CODER_SESSION_TOKEN
```

## Testing

Added `TestLogin/SessionTokenEnvVar` that verifies the error is returned
when the env var is set.
This commit is contained in:
Danny Kopping
2026-03-10 09:41:05 +00:00
committed by GitHub
parent 14341edfc2
commit d936a99e6b
2 changed files with 26 additions and 0 deletions
+14
View File
@@ -356,6 +356,20 @@ func (r *RootCmd) login() *serpent.Command {
return nil
}
// If CODER_SESSION_TOKEN is set in the environment, abort login.
// The env var takes precedence over a token stored on disk, so
// even if we complete login and write a new token to the session
// file, subsequent CLI commands would still use the environment
// variable value.
if inv.Environ.Get(envSessionToken) != "" {
return xerrors.Errorf(
"%s is set. This environment variable takes precedence over any session token stored on disk.\n\n"+
"To log in, unset the environment variable and re-run this command:\n\n"+
"\tunset %s",
envSessionToken, envSessionToken,
)
}
sessionToken, _ := inv.ParsedFlags().GetString(varToken)
if sessionToken == "" {
authURL := *serverURL
+12
View File
@@ -516,6 +516,18 @@ func TestLogin(t *testing.T) {
require.NotEqual(t, client.SessionToken(), sessionFile)
})
t.Run("SessionTokenEnvVar", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
root, _ := clitest.New(t, "login", client.URL.String())
root.Environ.Set("CODER_SESSION_TOKEN", "invalid-token")
err := root.Run()
require.Error(t, err)
require.Contains(t, err.Error(), "CODER_SESSION_TOKEN is set")
require.Contains(t, err.Error(), "unset CODER_SESSION_TOKEN")
})
t.Run("KeepOrganizationContext", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)