{"id":92,"library":"jira","title":"Jira API (Python)","description":"Two separate community-maintained Python libraries exist for Jira: 'jira' (pip install jira, v3.10.5) and 'atlassian-python-api' (pip install atlassian-python-api, v4.0.7). Neither is an official Atlassian SDK. They have different APIs, auth patterns, and JQL methods. Agents frequently mix them up.","status":"active","version":"3.10.5 (jira) / 4.0.7 (atlassian-python-api)","language":"python","source_language":"en","source_url":"https://github.com/pycontribs/jira","tags":["jira","atlassian","project-management","issue-tracker","api","python"],"install":[{"cmd":"pip install jira","lang":"bash","label":"Python (jira package — pycontribs)"},{"cmd":"pip install atlassian-python-api","lang":"bash","label":"Python (atlassian-python-api — atlassian-api)"}],"dependencies":[],"imports":[{"note":"jira package uses JIRA (uppercase). atlassian-python-api uses Jira (mixed case). Mixing them causes ImportError or silent wrong-class usage.","wrong":"from atlassian import JIRA","symbol":"JIRA","correct":"from jira import JIRA"},{"note":"atlassian-python-api exports Jira (mixed case). jira package exports JIRA (uppercase). The casing difference is the only signal which package you're using.","wrong":"from jira import Jira","symbol":"Jira","correct":"from atlassian import Jira"}],"quickstart":{"code":"# --- Option A: jira package (pycontribs) ---\nfrom jira import JIRA\n\njira = JIRA(\n    server='https://your-domain.atlassian.net',\n    basic_auth=('your-email@example.com', 'your-api-token')\n)\nissue = jira.issue('PROJ-1')\nprint(issue.fields.summary)\n\n# --- Option B: atlassian-python-api ---\nfrom atlassian import Jira\n\njira = Jira(\n    url='https://your-domain.atlassian.net',\n    username='your-email@example.com',\n    password='your-api-token',\n    cloud=True  # required for Cloud\n)\ndata = jira.enhanced_jql('project = PROJ ORDER BY created DESC')\nprint(data)","lang":"python","description":"Both packages side-by-side. Pick one and stay consistent."},"warnings":[{"fix":"Pick one. 'jira' is better for pure Jira work. 'atlassian-python-api' covers Confluence/Bitbucket/ServiceDesk too.","message":"Two competing packages: 'jira' (imports as JIRA) and 'atlassian-python-api' (imports as Jira). Tutorials and LLM-generated code mix them constantly. They are not interchangeable.","severity":"breaking","affected_versions":"all"},{"fix":"Generate token at id.atlassian.com/manage-profile/security/api-tokens. Pass as password= (jira pkg) or password= (atlassian pkg).","message":"Jira Cloud blocks password auth. API token must be passed as the password field, not an actual password. Regular account passwords return 401 or 404 (often with 'Issue does not exist or you do not have permission to see it' and 'X-Seraph-Loginreason: AUTHENTICATED_FAILED' headers).","severity":"breaking","affected_versions":"all"},{"fix":"Always pass cloud=True when connecting to *.atlassian.net","message":"atlassian-python-api: cloud=True is required for Jira Cloud. Omitting it causes requests to fail against Cloud endpoints silently or with confusing 404s.","severity":"breaking","affected_versions":"all"},{"fix":"Replace jira.jql(...) with jira.enhanced_jql(...) for Cloud instances.","message":"atlassian-python-api: jql() method is deprecated for Jira Cloud. Use enhanced_jql() instead.","severity":"breaking","affected_versions":"all"},{"fix":"Server/DC: Jira(url=..., token=pat_token). Cloud: Jira(url=..., username=email, password=api_token, cloud=True)","message":"Jira Server/Data Center uses Personal Access Token (PAT) via token= parameter. Jira Cloud uses API token via username+password. The auth pattern differs by deployment type.","severity":"gotcha","affected_versions":"all"},{"fix":"Pass maxResults=False or paginate with startAt parameter to retrieve all results.","message":"jira package: search_issues() returns max 50 results by default. Silent truncation — no error raised if results exceed limit.","severity":"gotcha","affected_versions":"all"},{"fix":"For production use, pin versions. Both packages have had breaking changes between minor versions.","message":"Neither package is an official Atlassian product. Atlassian has no official Python SDK. Both are community-maintained.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T07:59:28.603Z","next_check":"2026-06-17T00:00:00.000Z","problems":[{"fix":"For Jira Cloud, use your Atlassian email address as the username and a generated API token as the password. Ensure the API token has the necessary permissions. Example for 'jira' library: `jira = JIRA(server='https://your-domain.atlassian.net', basic_auth=('your_email@example.com', 'YOUR_API_TOKEN'))`. Example for 'atlassian-python-api' library: `jira = Atlassian(url='https://your-domain.atlassian.net', username='your_email@example.com', password='YOUR_API_TOKEN')`","cause":"This error typically occurs when the authentication credentials provided are incorrect, such as using a password instead of an API token, an incorrect email/username, or an expired/revoked API token, or due to insufficient permissions.","error":"jira.exceptions.JIRAError: JiraError HTTP 401 url: <JIRA_URL> text: Client must be authenticated to access this resource."},{"fix":"Install the required library using pip. If using the 'jira' library: `pip install jira`. If using 'atlassian-python-api': `pip install atlassian-python-api`. Ensure you install it in the correct virtual environment if one is being used.","cause":"The Python interpreter cannot find the 'jira' module because it is either not installed in the active environment or the environment path is incorrectly configured.","error":"ModuleNotFoundError: No module named 'jira'"},{"fix":"Verify that the object you are calling `.fields` on is indeed a `jira.resources.Issue` instance. For attributes that might be `None`, add explicit checks: `if issue.fields.assignee: print(issue.fields.assignee.displayName)`. For fields that require explicit loading (like 'worklog'), use the `expand` parameter when fetching the issue: `issue = jira.issue('ISSUE-KEY', expand='changelog,worklog')`.","cause":"This error often indicates that you are attempting to access an attribute (like `fields`) on an object that is not a valid `jira.resources.Issue` instance, or an attribute that is lazily loaded and not retrieved by default. A related common error is `AttributeError: 'NoneType' object has no attribute 'name'` when an optional field (like assignee) is not present on an issue.","error":"AttributeError: '<class 'jira.resources.Issue'> object has no attribute 'fields'"},{"fix":"Examine the `text` portion of the error message for specific details on what is incorrect. Adjust your payload to include all mandatory fields with correct data types and formats as per your Jira instance's configuration (e.g., provide values for all required custom fields for the issue type being created).","cause":"This 'Bad Request' error means the data sent to the Jira API is malformed, incomplete, or violates Jira's validation rules for the specific operation (e.g., missing a required field, invalid field format, or an issue type that does not exist in the project).","error":"jira.exceptions.JIRAError: JiraError HTTP 400 url: <JIRA_URL> text: <Specific Jira API error message>"},{"fix":"Upgrade the 'jira' Python library to the latest version using `pip install --upgrade jira`. If the problem persists after upgrading, review your code to ensure it's not explicitly targeting API v2 endpoints and is compatible with the API v3 changes, particularly for search queries.","cause":"This error occurs because Jira Cloud has deprecated and removed its API v2 search endpoint. Your current code or an older version of the `jira` Python library is still attempting to use this retired endpoint.","error":"jira.exceptions.JIRAError: JiraError HTTP 410 url: <JIRA_URL>/rest/api/2/search text: The requested API has been removed. Please migrate to the /rest/api/3/search/jql API."}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.59,"mem_mb":12,"disk_size":"25.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.43,"mem_mb":12,"disk_size":"25M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.84,"mem_mb":13.3,"disk_size":"27.5M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.7,"mem_mb":13.3,"disk_size":"28M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.73,"mem_mb":13,"disk_size":"19.2M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.76,"mem_mb":13,"disk_size":"20M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.69,"mem_mb":13.3,"disk_size":"18.8M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.71,"mem_mb":13.3,"disk_size":"19M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.63,"mem_mb":15.1,"disk_size":"41.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.54,"mem_mb":15.1,"disk_size":"43M"}]},"quickstart_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}