{"record":{"id":"b1433e3f2a89a881","repo":"infiniflow/ragflow","slug":"jira-credential-appears-to-be-invalid-or-expired","errorCode":null,"errorMessage":"Jira credential appears to be invalid or expired (HTTP 401).","messagePattern":"Jira credential appears to be invalid or expired \\(HTTP 401\\)\\.","errorType":"validation","errorClass":"InsufficientPermissionsError","httpStatus":401,"severity":"error","filePath":"common/data_source/jira/connector.py","lineNumber":281,"sourceCode":"                attempt_start,\n                adjusted_start,\n                end,\n                self.time_buffer_seconds,\n            )\n            try:\n                return (yield from self._load_from_checkpoint_internal(jql, checkpoint, start_filter=start))\n            except Exception as exc:\n                if attempt_start is not None and not retried_with_buffer and is_atlassian_date_error(exc):\n                    attempt_start = attempt_start - ONE_HOUR\n                    retried_with_buffer = True\n                    logger.info(f\"[Jira] Atlassian date error detected; retrying with start={attempt_start}.\")\n                    continue\n                raise\n\n    def _handle_validation_error(self, exc: Exception) -> None:\n        status_code = getattr(exc, \"status_code\", None)\n        if status_code == 401:\n            raise InsufficientPermissionsError(\"Jira credential appears to be invalid or expired (HTTP 401).\") from exc\n        if status_code == 403:\n            raise InsufficientPermissionsError(\"Jira token does not have permission to access the requested resources (HTTP 403).\") from exc\n        if status_code == 404:\n            raise ConnectorValidationError(\"Jira resource not found (HTTP 404).\") from exc\n        if status_code == 429:\n            raise ConnectorValidationError(\"Jira rate limit exceeded during validation (HTTP 429).\") from exc\n\n        message = getattr(exc, \"text\", str(exc))\n        if not message:\n            raise UnexpectedValidationError(\"Unexpected Jira validation error.\") from exc\n\n        raise ConnectorValidationError(f\"Jira validation failed: {message}\") from exc\n\n    def _load_from_checkpoint_internal(\n        self,\n        jql: str,\n        checkpoint: JiraCheckpoint,\n        start_filter: SecondsSinceUnixEpoch | None = None,","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/jira/connector.py#L263-L299","documentation":"InsufficientPermissionsError raised by _handle_validation_error when a caught Jira exception exposes status_code == 401. Authentication was attempted and rejected: the API token or basic-auth password is wrong, expired, or revoked. It chains the original exception (from exc) so the server response is inspectable on __cause__.","triggerScenarios":"validate_connector_settings() or its JQL validation search returning HTTP 401 from the Jira REST API - an expired Atlassian API token, a revoked token, a wrong password, or an email/token mismatch for basic auth.","commonSituations":"Atlassian API tokens past their expiry policy; tokens revoked when a user leaves or rotates credentials; environment-specific token variables out of sync across deployments; password basic auth against Cloud where it is disabled.","solutions":["Generate a new API token in Atlassian account settings and update the credential payload.","Confirm the token is paired with the correct account (token_auth needs no email; basic_auth needs the exact username).","Check __cause__ for the raw response body to confirm the rejection reason (e.g. 'Basic authentication with passwords is deprecated').","If using basic auth against Cloud, switch to token_auth - password auth is disabled there."],"exampleFix":"# before\ncreds = {'jira_user_email': 'dev@acme.com', 'jira_password': 'old-password'}  # Cloud: 401\n\n# after\ncreds = {'jira_user_email': 'dev@acme.com', 'jira_api_token': os.environ['JIRA_API_TOKEN']}","handlingStrategy":"try-catch","validationCode":"def jira_token_still_valid(base_url: str, token: str) -> bool:\n    import requests\n    r = requests.get(f'{base_url.rstrip(\"/\")}/rest/api/3/myself',\n                     headers={'Authorization': f'Bearer {token}'}, timeout=10)\n    return r.status_code != 401","typeGuard":null,"tryCatchPattern":"try:\n    connector.validate_connector_settings()\nexcept InsufficientPermissionsError as e:\n    if 'HTTP 401' in str(e):\n        trigger_credential_renewal(user_id)  # prompt user to re-enter the token\n    raise","preventionTips":["Pre-validate tokens with a /rest/api/3/myself probe when credentials are saved.","Rotate Atlassian API tokens on a schedule before expiry.","Surface 401 as 're-authenticate' in user-facing flows, distinct from permission errors."],"tags":["jira","authentication","http-401","permissions"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}