Tencent/WeKnora · error
OAuth token response did not contain an access_token
Error message
OAuth token response did not contain an access_token
What it means
SaveToken persists a transport.Token but refuses to store a nil token or one with an empty AccessToken — such a token is unusable for authenticated requests. This error indicates the OAuth token endpoint response was malformed or the exchange produced no access token.
Source
Thrown at internal/mcp/oauth_tokenstore.go:88
}
if row == nil || row.AccessToken == "" {
return nil, transport.ErrNoToken
}
return &transport.Token{
AccessToken: row.AccessToken,
RefreshToken: row.RefreshToken,
TokenType: row.TokenType,
ExpiresAt: row.ExpiresAt,
}, nil
}
// SaveToken persists a freshly issued or refreshed token.
func (s *dbTokenStore) SaveToken(ctx context.Context, token *transport.Token) error {
if err := ctx.Err(); err != nil {
return err
}
if token == nil || token.AccessToken == "" {
return fmt.Errorf("OAuth token response did not contain an access_token")
}
if token.TokenType == "" {
token.TokenType = "Bearer"
}
expiresAt := token.ExpiresAt
if expiresAt.IsZero() && token.ExpiresIn > 0 {
expiresAt = time.Now().Add(time.Duration(token.ExpiresIn) * time.Second)
}
principal := s.principal.Normalize()
return s.repo.SaveTokenForPrincipal(ctx, &types.MCPOAuthToken{
TenantID: s.tenantID,
PrincipalType: principal.Type,
PrincipalID: principal.ID,
UserID: principal.StorageID(),
ServiceID: s.serviceID,
AccessToken: token.AccessToken,
RefreshToken: token.RefreshToken,
TokenType: token.TokenType,View on GitHub (pinned to 988cbb0330)
Solutions
- Inspect the token exchange response before SaveToken: log (redacted) status code and body to see whether the provider returned an error like invalid_grant.
- Verify client_id/client_secret, redirect_uri, and authorization code are correct and the code was not already consumed (codes are single-use).
- Check your provider's token response field name matches what transport.Token parsing expects (access_token).
- Never call SaveToken after a failed exchange — gate it on a successful, non-empty exchange result.
Example fix
// before
tok, _ := exchange(ctx, code)
store.SaveToken(ctx, tok)
// after
tok, err := exchange(ctx, code)
if err != nil { return fmt.Errorf("token exchange failed: %w", err) }
if tok == nil || tok.AccessToken == "" {
return fmt.Errorf("exchange returned no access token; check provider error response")
}
return store.SaveToken(ctx, tok) Defensive patterns
Strategy: validation
Validate before calling
if token == nil || token.AccessToken == "" {
return fmt.Errorf("refusing to save token: exchange returned no access_token")
} Type guard
func hasAccessToken(t *transport.Token) bool {
return t != nil && t.AccessToken != ""
} Try / catch
if err := store.SaveToken(ctx, token); err != nil {
if strings.Contains(err.Error(), "did not contain an access_token") {
return fmt.Errorf("token exchange failed; verify provider credentials and error response: %w", err)
}
return err
} Prevention
- Check the exchange error before constructing/saving a token.
- Log provider error bodies (redacted) on exchange failure to spot invalid_grant/invalid_client.
- Validate redirect_uri and code single-use semantics against your provider.
- Confirm the provider's token response field name (access_token) matches your transport's parser.
When it happens
Trigger: SaveToken called with a nil *transport.Token, or with a token whose AccessToken field is empty (provider returned error/JSON without access_token, or the token struct was constructed without the access token).
Common situations: OAuth provider returned 4xx with a JSON body the transport parsed into an empty token; wrong token endpoint or client credentials caused an error response; provider uses a nonstandard field name for the access token; network proxy stripped the response body.
Related errors
- MCP service URL is required for OAuth
- MCP service %s does not use OAuth
- principal context is required to authorize OAuth MCP service
- invite code has expired
- join request not found
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/dfbc157cfe3ce740.
Report an issue: GitHub.