Reported downstream as eman/ha_nwp500#131 (HA 2026.8.3, ha_nwp500 0.20.0 pinned to nwp500-python 9.3.1). Filing here because the failure is in this library's model, not in the integration.
Symptom
/device/list is unparseable and the whole device is lost, so the Home Assistant integration cannot set up ("Failed setup, will retry"):
Error communicating with API: 2 validation errors for Device
error.errorCode.int-enum[ErrorCode]
Input should be 0, 96, 97, 326, ... or 990 [type=enum, input_value=None, input_type=NoneType]
error.errorCode.int
Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]
Cause
The cloud returns "error": {"errorCode": null} on at least some devices. DeviceErrorSummary.error_code (added in 9.3.1, #124) is typed ErrorCode | int with union_mode="left_to_right" — neither branch accepts None, so a null fails validation of the entire Device, and with it the whole listing. Rolling back to a version before 9.3.1, where the error block was unmodelled and silently ignored, restores service.
Both the enum-vs-int union and the errorOccuredTime/descaling/modelTypeCode fields were already made null-tolerant; errorCode is the one that wasn't.
Fix
Type it ErrorCode | int | None defaulting to None. A null means the cloud reported no code, which is not the same claim as NO_ERROR, so mapping null to 0 would assert something the cloud didn't say — and both known consumers (sensor.py's cloud_error_code, diagnostics.py) already handle None by reporting nothing. Callers that assumed the field was always present need to handle None.
Note this makes error_code nullable in docs/openapi.yaml too.
Reported downstream as eman/ha_nwp500#131 (HA 2026.8.3, ha_nwp500 0.20.0 pinned to nwp500-python 9.3.1). Filing here because the failure is in this library's model, not in the integration.
Symptom
/device/listis unparseable and the whole device is lost, so the Home Assistant integration cannot set up ("Failed setup, will retry"):Cause
The cloud returns
"error": {"errorCode": null}on at least some devices.DeviceErrorSummary.error_code(added in 9.3.1, #124) is typedErrorCode | intwithunion_mode="left_to_right"— neither branch acceptsNone, so a null fails validation of the entireDevice, and with it the whole listing. Rolling back to a version before 9.3.1, where theerrorblock was unmodelled and silently ignored, restores service.Both the enum-vs-int union and the
errorOccuredTime/descaling/modelTypeCodefields were already made null-tolerant;errorCodeis the one that wasn't.Fix
Type it
ErrorCode | int | Nonedefaulting toNone. A null means the cloud reported no code, which is not the same claim asNO_ERROR, so mapping null to 0 would assert something the cloud didn't say — and both known consumers (sensor.py'scloud_error_code,diagnostics.py) already handleNoneby reporting nothing. Callers that assumed the field was always present need to handleNone.Note this makes
error_codenullable indocs/openapi.yamltoo.