Improve diagnostics when env-based GITLAB_TOKEN is expired (e.g. via 1Password alias) but a valid PAT exists
### Summary `glab auth` can report `401 invalid_token` even when the user has a valid PAT in their shell/config, because an env-based token injected by a wrapper (e.g. 1Password `op plugin run -- glab`) takes precedence. Today, `glab` doesn’t clearly surface *which* token source it’s using, which makes this very hard to debug. ### What happened - I created a new PAT on gitlab.com: - Expires: 2027-03-24 - Has sufficient scopes - In a fresh zsh session: - `GITLAB_TOKEN` in my shell was set to this new PAT. - `curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" https://gitlab.com/api/v4/user` worked and returned my user JSON. - Running `glab auth login` and pasting the same token, or putting it into `config.yml`, still failed: - `glab auth status` showed: - `API call failed: GET https://gitlab.com/api/v4/user: 401 {error: invalid_token}, {error_description: Token is expired. You can either do re-authorization or token refresh.}` - `Token found: **************************` - `! One of GITLAB_TOKEN, GITLAB_ACCESS_TOKEN, OAUTH_TOKEN environment variables is set. It will be used for all authentication.` - In the PAT management UI on gitlab.com, the new PAT showed `Last used: never` (until I used it via `curl`), which suggested `glab` wasn’t actually using that token at all. - Eventually we discovered: `which glab` `# glab: aliased to op plugin run -- glab` 1Password’s `op plugin run` was injecting an *expired* token as `GITLAB_TOKEN`, which `glab` then used for all auth. That expired token was what was failing with `invalid_token`, not the new PAT set in my shell/config. - After updating the token stored in 1Password (so the alias injected a valid token), `glab auth status` succeeded. ### Why this is confusing - From the user’s perspective: - The token they *just created* works fine with `curl`. - `glab` says it “found a token” and that an env var will be used, but doesn’t say which one or where it came from. - The GitLab UI shows the new token as never used, reinforcing the idea that `glab` might be broken or ignoring the token. - The root cause (a wrapper/alias like `op plugin run -- glab` injecting a different `GITLAB_TOKEN`) is not obvious, especially if you set a correct `GITLAB_TOKEN` in your shell too. ### Environment - OS: macOS - Install: Homebrew - glab version: 1.90.0 (also reproduced on 1.73.0) - Git operations configured via SSH - Auth via PAT on gitlab.com - `glab` actually executed through `alias glab='op plugin run -- glab'` (1Password CLI plugin) ### Possible improvements I don’t expect `glab` to magically know it’s being invoked via a shell alias, but a few things could make this *much* easier to debug: 1. **Surface the exact token source in `auth status` / debug output** - Instead of only: > One of GITLAB_TOKEN, GITLAB_ACCESS_TOKEN, OAUTH_TOKEN environment variables is set. It will be used for all authentication. - Explicitly say which one is in use, e.g.: > Using token from environment variable: `GITLAB_TOKEN` - Optionally, in `GLAB_DEBUG=1`, log something like: > Token source: environment (GITLAB_TOKEN), origin: process environment - (No need to log the full token, maybe just first/last 4 chars.) 2. **Make the 401/invalid_token messaging more actionable** - When we get `401 invalid_token` on `/user` and we’re using an environment token, add guidance such as: - “Authentication failed using token from environment variable `GITLAB_TOKEN`. Check for wrappers/aliases (e.g., 1Password `op plugin run -- glab`) that might be setting this variable.” 3. **Document env-var precedence and common wrapper patterns** - In the auth docs, clearly state: - Env vars (`GITLAB_TOKEN`, `GITLAB_ACCESS_TOKEN`, `OAUTH_TOKEN`) take precedence over config. - Tools like 1Password may inject these automatically via aliases/wrappers. - Add a short troubleshooting section: “`glab auth status` says token is expired but your PAT works with curl” → steps to check: - `which glab` - `env | grep -E 'GITLAB_TOKEN|GITLAB_ACCESS_TOKEN|OAUTH_TOKEN'` 4. (Optional) **CLI flag to ignore env tokens** - Something like `GLAB_IGNORE_ENV_TOKEN=1` or a `--ignore-env-token` flag for debugging, so users can force `glab` to use the config token when they suspect env interference. ### Request Please consider: - Enhancing `glab auth status` and/or debug logging to clearly show **which** token source is in use (and from which env var). - Improving the error message when `401 invalid_token` is returned while using an env-based token, with a hint about wrappers/aliases and how to debug them. - Updating docs with a short troubleshooting section specifically for this scenario (1Password/other credential helpers injecting `GITLAB_TOKEN`). I’m happy to help refine wording or test any changes on macOS with a 1Password-based alias setup.
issue