{"record":{"id":"8b99eb8bdc437ddb","repo":"infiniflow/ragflow","slug":"jira-token-does-not-have-permission-to-access-the","errorCode":null,"errorMessage":"Jira token does not have permission to access the requested resources (HTTP 403).","messagePattern":"Jira token does not have permission to access the requested resources \\(HTTP 403\\)\\.","errorType":"validation","errorClass":"InsufficientPermissionsError","httpStatus":403,"severity":"error","filePath":"common/data_source/jira/connector.py","lineNumber":283,"sourceCode":"                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,\n    ) -> Generator[Document | ConnectorFailure, None, JiraCheckpoint]:\n        assert self.jira_client, \"load_credentials must be called before loading issues.\"","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/jira/connector.py#L265-L301","documentation":"InsufficientPermissionsError raised by _handle_validation_error when the Jira exception carries status_code == 403. Authentication succeeded but the authenticated identity lacks permission for the request - the token's scopes, the user's project roles, or admin-tier requirements block the operation. Chained from the original exception for response details.","triggerScenarios":"A scoped or automation token without read scope for the target project; a user who is not a member of the project; a JQL query referencing projects the identity cannot see; fetching comments or attachments where the identity has issue-view but not comment-view rights.","commonSituations":"Scoped tokens created for one product or site and used on another; service accounts added to Jira but not granted the project role; org-level restrictions on automation tokens.","solutions":["Grant the identity read access (Browse Projects plus view issues/comments) on the target project, or use a token with broader scopes.","Narrow the jql_query or project_key to resources the identity can access.","Inspect the __cause__ response text - Jira names the missing permission.","If scoped_token=True, verify the token's scopes include read for Jira on that site."],"exampleFix":"# before\nconnector = JiraConnector(jira_base_url=url, jql_query='project = SECRET')  # user lacks access -> 403\n\n# after\n# (admin) add the user to project SECRET with role 'Users', or narrow the scope:\nconnector = JiraConnector(jira_base_url=url, jql_query='project = OPS')","handlingStrategy":"try-catch","validationCode":"def jira_can_read_project(base_url: str, token: str, project_key: str) -> bool:\n    import requests\n    r = requests.get(f'{base_url.rstrip(\"/\")}/rest/api/3/project/{project_key}',\n                     headers={'Authorization': f'Bearer {token}'}, timeout=10)\n    return r.status_code == 200","typeGuard":null,"tryCatchPattern":"try:\n    connector.validate_connector_settings()\nexcept InsufficientPermissionsError as e:\n    if 'HTTP 403' in str(e):\n        log.warning('Token authenticated but lacks access; check project roles/scopes: %s', e.__cause__)\n    raise","preventionTips":["Grant service accounts the minimum project role (Browse Projects) during onboarding.","For scoped tokens, verify scopes cover Jira read on the target site.","Keep JQL scoped to projects the identity can access; test queries as that user first."],"tags":["jira","permissions","http-403","authorization"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}