Skip to content

Setup fails on servers with no array disks (null parity fields, string capacity values) #57

@itskevinb

Description

@itskevinb

Description

Integration v1.5.1 fails with "Received invalid data from Unraid" on servers that have no array disks and have never run a parity check. The GraphQL API returns types that the Pydantic models don't accept.

Additionally, the call_api method in api/__init__.py has no timeout on the session.post() call. When HA's event loop is busy during startup, the setup task gets cancelled (asyncio.CancelledError / "Setup cancelled") before the request completes.

Environment

  • Home Assistant 2026.4.1
  • Unraid API integration v1.5.1
  • Unraid 7.2.4 (server with no array disks configured)
  • Unraid API version 4.32.1

Root Cause

The GraphQL API on a server with no array disks returns:

{
  "array": {
    "capacity": {
      "kilobytes": {
        "free": "0",    // string, not int
        "used": "0",    // string, not int
        "total": "0"    // string, not int
      }
    },
    "parityCheckStatus": {
      "date": null,        // null, model expects datetime
      "duration": null,    // null, model expects int
      "speed": "0",        // string, model expects float
      "status": "NEVER_RUN",
      "errors": null,
      "progress": 0
    }
  }
}

The strict Pydantic models in api/v4_20.py reject these types, causing a ValidationError which is caught as UnraidApiInvalidResponseError.

Fix

Three files need changes:

1. api/__init__.py — Add timeout to call_api

from aiohttp import ClientTimeout

# In call_api method:
response = await self.session.post(
    self.endpoint,
    json={"query": query, "variables": variables or {}},
    headers={...},
    timeout=ClientTimeout(total=30),  # Add this
)

2. api/v4_20.py — Widen model types

class ArrayCapacityKilobytes(BaseModel):
    free: int | str    # was: int
    used: int | str    # was: int
    total: int | str   # was: int

class ParityCheck(BaseModel):
    date: datetime | None    # was: datetime
    duration: int | None     # was: int
    speed: float | str       # was: float
    status: ParityCheckStatus
    errors: int | None
    progress: int

And convert in query_metrics_array:

capacity_free=int(response.array.capacity.kilobytes.free),
capacity_used=int(response.array.capacity.kilobytes.used),
capacity_total=int(response.array.capacity.kilobytes.total),
parity_check_speed=float(response.array.parity_check.speed) if response.array.parity_check.speed is not None else 0.0,

3. models.py — Match nullable types

@dataclass
class MetricsArray:
    ...
    capacity_free: int | str    # was: int
    capacity_used: int | str    # was: int
    capacity_total: int | str   # was: int
    ...
    parity_check_date: datetime | None    # was: datetime
    parity_check_duration: int | None     # was: int
    parity_check_speed: float | str       # was: float

The same changes apply to api/v4_26.py which inherits from v4_20.

Workaround

Apply the patches above manually inside the HA container at /config/custom_components/unraid_api/. They will be overwritten on the next HACS update.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions