Skip to content

[BUG] GitLab OAuth token not auto-refreshed on 401 during session #9711

Closed

Description

@VilgelmOne

Description

When using GitLab Duo with OAuth authentication, if the access token expires during an active opencode session, the error GitLabError: Failed to get direct access token: 401 Unauthorized - {"error":"invalid_token","error_description":"Token is expired. You can either do re-authorization or token refresh."} occurs.

Restarting opencode fixes the issue because the loader function in @gitlab/opencode-gitlab-auth plugin has auto-refresh logic that runs at startup.

Root Cause

The GitLab auth plugin (@gitlab/opencode-gitlab-auth@1.3.0) has a refreshTokenIfNeeded() function that correctly handles token refresh, but it's only called in the loader() function during provider initialization.

When the token expires mid-session:

  1. The GitLab API returns 401
  2. opencode doesn't catch this error and trigger a token refresh
  3. The user has to restart opencode

Expected Behavior

opencode should intercept 401 "invalid_token" errors from GitLab API and automatically:

  1. Call the refresh token flow
  2. Retry the failed request with the new token

Workaround

Restart opencode — the token will be refreshed on startup.

Environment

  • opencode version: 1.1.28
  • @gitlab/opencode-gitlab-auth: 1.3.0
  • OS: macOS

auth.json structure

{
  "gitlab": {
    "type": "oauth",
    "access": "...",
    "refresh": "...",
    "expires": 1768953223555,
    "enterpriseUrl": "https://gitlab.com"
  }
}

Suggestion

Add retry logic with token refresh in the GitLab provider's custom fetch or in the SDK error handling:

// In provider.ts gitlab custom loader
gitlab: async (input) => {
  // ... existing code ...
  return {
    autoload: !!apiKey,
    options: {
      // ... existing options ...
      fetch: async (input, init) => {
        const response = await fetch(input, init)
        if (response.status === 401) {
          const body = await response.clone().json().catch(() => ({}))
          if (body.error === 'invalid_token') {
            // Trigger token refresh and retry
            await refreshGitLabToken(providerID)
            // Retry with new token
            const newAuth = await Auth.get(providerID)
            if (newAuth?.type === 'oauth') {
              const headers = new Headers(init?.headers)
              headers.set('Authorization', `Bearer ${newAuth.access}`)
              return fetch(input, { ...init, headers })
            }
          }
        }
        return response
      }
    }
  }
}

Activity

  1. github-actions commented on Jan 20, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Feel free to ignore if none of these address your specific case.

  2. vglafirov commented on Jan 21, 2026

    @vglafirov
    Contributor

    Thanks for opening the issue and suggested fix. I knew about this problem. It was in my todo list. I will try to get this resolved asap.

  3. nicehiro commented on Jan 21, 2026

    @nicehiro

    Just confirmed the issue existed when using ChatGPT OAuth authentication.

  4. vglafirov commented on Jan 21, 2026

    @vglafirov
    Contributor

    @nicehiro Not sure what you mean. The issue isn't related to GitLab Duo provider?

  5. nicehiro commented on Jan 21, 2026

    @nicehiro

    @nicehiro Not sure what you mean. The issue isn't related to GitLab Duo provider?

    I’m not sure whether this is related to the GitLab Duo provider, but I’m seeing the same error (Error: Token refresh failed: 401) when using ChatGPT OAuth authentication. It was working normally moments ago, and then it suddenly started failing with this error.

  6. vglafirov commented on Jan 21, 2026

    @vglafirov
    Contributor

    Let me clarify. You use ChatGPT Oauth to authenticate with OpenAI provider and it thrown 401 immediately or after some time, when token expires? Or you are trying to authenticate to Gitlab Duo, using ChatGPT OAuth? 🤔

  7. rekram1-node commented on Jan 21, 2026

    @rekram1-node
    Collaborator

    @vglafirov I think it's an issue in multiple auth plugins, but it is a bug in the plugins themselves (including ours) afaik, since all the refresh logic is self contained to a plugin each one needs to implement proper refresh logic

  8. added a commit that references this issue on Jan 22, 2026
    6bdb469
  9. keramblock commented on Jan 22, 2026

    @keramblock

    can confirm that error(Error: Token refresh failed: 401) exists for openai codex connector

  10. LiJie298 commented on Jan 23, 2026

    @LiJie298

    那么该如何快速解决呢

  11. keramblock commented on Jan 23, 2026

    @keramblock

    那么该如何快速解决呢

    I don't know Chinese, but if Google Translate is correct, you just need to do this to reissue token:

    1. opencode auth logout
    2. opencode auth login
  12. SardorbekR commented on Jan 26, 2026

    @SardorbekR

    @keramblock cannot find logout button though😅 checked everywhere

  13. GreenStage commented on Jan 26, 2026

    @GreenStage
    Contributor

    +1

  14. Akswii commented on Jan 27, 2026

    @Akswii

    type the commands in your terminal @SardorbekR

  15. vglafirov commented on Feb 18, 2026

    @vglafirov
    Contributor

    With #13850 merged and release, this issue has been fixed.

  16. github-actions commented on Apr 20, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions