Repository navigation
fix: handle Unraid API 4.37.8 nullable roots and disabled introspection - #137
Conversation
…on (#135) - query() raises UnraidAPIError when every returned root is null with errors, and the docker/vms readers no longer raise AttributeError. - Keep GraphQL errors from 4xx bodies (INTROSPECTION_DISABLED). - get_capabilities() treats a server refusing introspection as current (minus RETIRED_FIELDS), so VM UUIDs are requested again.
Codex review: redirected POSTs raised before the body was read, so INTROSPECTION_DISABLED fell back to permissive capabilities.
Codex review: a redirected 401/403 with a GraphQL body was raised as a plain UnraidAPIError, so get_capabilities() swallowed a revoked key.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 50 minutes. View limit details
Walkthrough
Priority: Severity of issue fixed: Medium Merge Risk:
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Pull Request
Description
Fixes #135. These are the two breaking changes from an audit of upstream Unraid API releases 4.37.7–4.37.9 (the library is aligned through 4.37.6, #129).
docker/vmsroots (unraid/api#2123, 4.37.8). A failed Docker or VM service now returns{"docker": null}plus errors instead ofdata: null.query()returned that as a partial result, and every reader'sresult.get("docker", {}).get(...)raisedAttributeError. ha-unraid only catches the library's exceptions for these optional services, so one stopped service would fail its whole system poll. Nowquery()raisesUnraidAPIError(with the GraphQL errors) when errors are present and every returned root is null, and the nine readers read the roots null-safely. A failed service is never reported as an empty list, which would make consumers prune entities.unraid/api#2095in 4.37.8 and #2129 in 4.37.9). These servers answerHTTP 400withextensions.code: INTROSPECTION_DISABLED.get_capabilities()fell back topermissive(), sotyped_get_vms()stopped requestinguuid; ha-unraid's VM UUID attributes have been empty since the dev server upgraded. The guard on the retired disk-removal mutation also always passed. Now:UnraidAPIError, including after a POST redirect.INTROSPECTION_DISABLEDselectsServerCapabilities.introspection_disabled(): every current field exceptRETIRED_FIELDS, and not permissive.permissive().No library operation exceeds the new request limits (
unraid/api#2121: 5,000 tokens, 100 aliases, cost 1,000, depth 20). All 72 argument-free read methods pass live on 4.37.9.Follow-up for detecting this automatically: #136 (an upstream watch workflow).
Type of Change
Pre-Submission Governance
Related Issues
Fixes #135
Changes Made
client.py:query(): a response with errors and only null roots raisesUnraidAPIError(errors=…). Partial results with at least one healthy root, and null roots without errors, are returned unchanged.(result.get("docker") or {})/(result.get("vms") or {})in the nine readers (containers, containers safe, VMs, update statuses, port conflicts, raw containers, raw VMs, networks, logs)._raise_for_graphql_rejection()keeps a 4xx response's GraphQLerrorson direct and redirected POSTs. A body without GraphQL errors keeps the existingHTTP error <status>message.get_capabilities()mapsINTROSPECTION_DISABLEDtoServerCapabilities.introspection_disabled().capabilities.py:RETIRED_FIELDS(ArrayMutations.removeDiskFromArray) andServerCapabilities.introspection_disabled().tests/test_api_4378_compat.py(new, 25 tests): every affected reader raisesUnraidAPIErroron a null root; partial results and errorless null roots still pass; 4xx GraphQL errors are kept directly and after a redirect; non-GraphQL 4xx bodies are unchanged; capability selection for both introspection outcomes; VMuuidis requested; retired disk removal is refused without a request; 401/403 after a redirect stayUnraidAuthenticationError.tests/test_client_async.py: one existing mock response gets thestatusa real response always has.Python Package & API Architecture Standards
py.typed)print()statements in package source code (uses standard logging)__repr__Testing Performed
pytest)rufforflake8)mypy)Test Results
Review: CodeRabbit is rate-limited, so Codex reviewed the branch locally in two passes.
INTROSPECTION_DISABLEDwas missed on servers that redirect (SSL modes).UnraidAPIError, soget_capabilities()would swallow a revoked key. The handler now leaves 401/403 to the authentication mapping.Documentation
Breaking Changes
None to signatures. Behaviour: on servers that refuse introspection, the client no longer uses permissive capabilities, and a query whose only roots come back null with errors now raises
UnraidAPIErrorinstead of returning{root: None}. That is what consumers already handled before 4.37.8, when such a response wasdata: null.Checklist
Disclosure: this PR was written with the help of AI (Claude Code). The "human reviewed" box above is left for the maintainer to tick after review.
Summary by CodeRabbit
Bug Fixes
Documentation