makeplane/plane · error · AuthenticationException
5115|5120|5121|5123|5104
5115|5120|5121|5123|5104
Error message
str(code)
What it means
Raised in OauthAdapter.get_user_token (oauth.py:84) when the POST to the provider's token URL raises requests.RequestException (network error or non-2xx via raise_for_status). The error code/message are dynamic: code = self.authentication_error_code(), so it resolves to GOOGLE_OAUTH_PROVIDER_ERROR (5115), GITHUB_OAUTH_PROVIDER_ERROR (5120), GITLAB_OAUTH_PROVIDER_ERROR (5121), GITEA_OAUTH_PROVIDER_ERROR (5123), or OAUTH_NOT_CONFIGURED (5104) for unknown providers. The message is str(code) — the constant NAME, not a human string.
Source
Thrown at apps/api/plane/authentication/adapter/oauth.py:84
def get_user_info_url(self):
return self.userinfo_url
def authenticate(self):
self.set_token_data()
self.set_user_data()
return self.complete_login_or_signup()
def get_user_token(self, data, headers=None):
try:
headers = headers or {}
response = requests.post(self.get_token_url(), data=data, headers=headers)
response.raise_for_status()
return response.json()
except requests.RequestException:
self.logger.warning("Error getting user token")
code = self.authentication_error_code()
raise AuthenticationException(error_code=AUTHENTICATION_ERROR_CODES[code], error_message=str(code))
def get_user_response(self):
try:
headers = {"Authorization": f"Bearer {self.token_data.get('access_token')}"}
response = requests.get(self.get_user_info_url(), headers=headers)
response.raise_for_status()
return response.json()
except requests.RequestException:
# Do not log headers here: they carry the access token
self.logger.warning("Error getting user response")
code = self.authentication_error_code()
raise AuthenticationException(error_code=AUTHENTICATION_ERROR_CODES[code], error_message=str(code))
def set_user_data(self, data):
self.user_data = data
def create_update_account(self, user):
try:View on GitHub (pinned to 1c8a60f858)
Solutions
- Check the backend log line 'Error getting user token' alongside provider docs for the failing token exchange (most often an expired/reused auth code or bad client_secret).
- Verify OAUTH_CLIENT_SECRET / *_CLIENT_SECRET and redirect_uri match the provider app configuration exactly.
- Confirm network egress from the API container to the provider's token URL is allowed.
- If self.provider is unrecognized, the code falls back to OAUTH_NOT_CONFIGURED — register the provider in authentication_error_code().
Example fix
# before: client_secret typo -> provider returns 401 -> RequestException -> 5120 # GITHUB_CLIENT_SECRET=correct-secret-value (env / instance config) # after: ensure token URL is reachable and credentials are correct
Defensive patterns
Strategy: retry
Validate before calling
import requests
def token_endpoint_reachable(token_url: str, timeout: float = 5.0) -> bool:
try:
# connectivity probe only; do NOT send real code/secret here
return requests.options(token_url, timeout=timeout).status_code < 500
except requests.RequestException:
return False Try / catch
from plane.authentication.adapter.error import AuthenticationException
try:
adapter.get_user_token(data)
except AuthenticationException as e:
if e.error_code in (5115, 5120, 5121, 5123, 5104):
log_oauth_token_failure(provider=adapter.provider, code=e.error_code)
prompt_user_retry()
else:
raise Prevention
- Keep OAuth credentials in instance config and validate them at deploy time.
- Ensure network egress to the provider's token URL from the API container.
- Do not reuse authorization codes — each OAuth callback exchanges a fresh code.
When it happens
Trigger: OAuth callback flow: the authorization code is exchanged at the provider's token endpoint. If the request times out, the endpoint returns 4xx/5xx, DNS fails, or the provider is unreachable, RequestException is caught and AuthenticationException is raised. Which numeric code you get depends entirely on self.provider.
Common situations: Expired or replayed authorization code (providers return 400 on second use), wrong client_secret (provider returns 401), redirect_uri mismatch, network egress restrictions to the OAuth provider, or the provider's token endpoint is down.
Related errors
- 5112
- Failed to fetch image: ${response.statusText}
- Failed to fetch image: ${response.statusText}
- Given API token is not valid
- Given API token is not valid
AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12).
Data as JSON: /api/errors/7f64c3880a547692.
Report an issue: GitHub.