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