fix: tolerate legacy NULL properties on pending devices

The pending_devices.properties column is added by an idempotent migration, so
existing rows have properties = NULL. PendingDeviceResponse typed it as a list,
so GET /scan/pending 500'd on any pre-existing device.

- Coerce NULL/non-list properties to [] in PendingDeviceResponse.
- Backfill existing NULL rows to '[]' in init_db migrations.
- Regression test: /scan/pending returns 200 with a legacy NULL-properties row.

ha-relevant: maybe
This commit is contained in:
Pouzor
2026-07-06 00:01:27 +02:00
parent ab36ba6f81
commit abefc42fdf
3 changed files with 24 additions and 1 deletions
+2
View File
@@ -117,6 +117,8 @@ async def init_db() -> None:
await conn.exec_driver_sql("ALTER TABLE pending_devices ADD COLUMN discovery_source TEXT")
with suppress(OperationalError):
await conn.exec_driver_sql("ALTER TABLE pending_devices ADD COLUMN properties JSON")
with suppress(OperationalError):
await conn.exec_driver_sql("UPDATE pending_devices SET properties = '[]' WHERE properties IS NULL")
with suppress(OperationalError):
await conn.exec_driver_sql("ALTER TABLE scan_runs ADD COLUMN kind TEXT NOT NULL DEFAULT 'ip'")
# --- Zigbee schema migrations (logged variant per CLAUDE.md feedback) ---
+7 -1
View File
@@ -1,7 +1,7 @@
from datetime import datetime
from typing import Any
from pydantic import BaseModel
from pydantic import BaseModel, field_validator
class PendingDeviceResponse(BaseModel):
@@ -35,6 +35,12 @@ class PendingDeviceResponse(BaseModel):
node_last_modified: datetime | None = None
node_last_seen: datetime | None = None
@field_validator("properties", mode="before")
@classmethod
def _coerce_properties(cls, v: Any) -> list[Any]:
# Legacy rows (column added by migration) have properties = NULL.
return v if isinstance(v, list) else []
model_config = {"from_attributes": True}