Repository: github.com/openconfig/ondatra
Affected Version: v0.14.1 (current latest, released Feb 18, 2026)
Severity: Medium — causes silent data loss and unmarshal error floods
Date: March 26, 2026
Summary
The openconfig-platform-healthz YANG model augments the /components/component
hierarchy with a healthz container that includes three leaves for monitoring
component health status. This model has been part of the OpenConfig public
schema since January 2023. However, the generated *oc.Component Go struct
in ondatra v0.14.1/gnmi/oc/structs-0.go does not contain a Healthz
field, causing unmarshal errors and silent data loss in any test that reads full
component state telemetry from a DUT that advertises healthz data.
Problem Details
YANG Model Definition
The openconfig-platform-healthz YANG model defines the following aug-
mentation:
YANG Path : /components/component/healthz/state/status
Type : enum
Description : Component health status: UNSPECIFIED, HEALTHY, UNHEALTHY
YANG Path : /components/component/healthz/state/last-unhealthy
Type : timeticks64
Description : Nanoseconds since Unix epoch when component was last unhealthy
YANG Path : /components/component/healthz/state/unhealthy-count
Type : uint64
Description : Counter for number of times component transitioned to unhealthy state
Source: openconfig-platform-healthz.yang
Module Revision: 2023-04-11 (v0.1.1)
YANG Augmentation:
module openconfig-platform-healthz {
// ... namespace and imports ...
augment "/oc-platform:components/oc-platform:component" {
description "Augment healthz information into the /components/component hierarchy.";
uses platform-health-top;
}
grouping platform-health-top {
container healthz {
container state {
config false;
leaf status {
type enumeration { enum UNSPECIFIED; enum HEALTHY; enum UNHEALTHY; }
oc-ext:telemetry-on-change;
}
leaf last-unhealthy { type oc-types:timeticks64; }
leaf unhealthy-count { type uint64; }
}
}
}
}
Generated Go Struct Issue
The *oc.Component struct in ondatra v0.14.1/gnmi/oc/structs-0.go is missing the Healthz field:
type Component struct {
AllocatedPower *uint32 path:"state/allocated-power" ...
Backplane *Component_Backplane path:"backplane" ...
BaseMacAddress *string path:"state/base-mac-address" ...
BootLoader *Component_BootLoader path:"boot-loader" ...
BootTime *uint64 path:"state/boot-time" ...
Chassis *Component_Chassis path:"chassis" ...
// ... other fields ...
HardwareVersion *string path:"state/hardware-version" ...
Id *string path:"state/id" ...
// � HEALTHZ FIELD IS MISSING HERE
InstallComponent *string path:"state/install-component" ...
// ... other fields continue ...
}
Runtime Error Messages
When a DUT advertises healthz state data and a test calls gnmi.GetAll(t,
dut, gnmi.OC().ComponentAny().State()), the following errors appear:
Unmarshal string_val:"UNHEALTHY" into origin:"openconfig"
elem:{name:"components"}
elem:{name:"component" key:{key:"name" value:"CHASSIS0"}}
elem:{name:"healthz"} elem:{name:"state"} elem:{name:"status"}:
path "/components/component[name=CHASSIS0]/healthz/state/status" is invalid and cannot be ma
to a generated GoStruct field: rpc error: code = InvalidArgument desc = no match found in *o
for path elem:{name:"healthz"} elem:{name:"state"} elem:{name:"status"}
Unmarshal uint_val:1774337554888000000 into origin:"openconfig"
elem:{name:"components"}
elem:{name:"component" key:{key:"name" value:"CHASSIS0"}}
elem:{name:"healthz"} elem:{name:"state"} elem:{name:"last-unhealthy"}:
path "/components/component[name=CHASSIS0]/healthz/state/last-unhealthy" is invalid and cann
to a generated GoStruct field: rpc error: code = InvalidArgument desc = no match found in *o
for path elem:{name:"healthz"} elem:{name:"state"} elem:{name:"last-unhealthy"}
Unmarshal uint_val:1 into origin:"openconfig"
elem:{name:"components"}
elem:{name:"component" key:{key:"name" value:"CHASSIS0"}}
elem:{name:"healthz"} elem:{name:"state"} elem:{name:"unhealthy-count"}:
path "/components/component[name=CHASSIS0]/healthz/state/unhealthy-count" is invalid and can
to a generated GoStruct field: rpc error: code = InvalidArgument desc = no match found in *o
for path elem:{name:"healthz"} elem:{name:"state"} elem:{name:"unhealthy-count"}
These errors appear once per healthz leaf per component, flooding test
output and making it difficult to diagnose real issues.
Root Cause Analysis
The openconfig-platform-healthz.yang model is not being included in the set of YANG models fed to ygen (the Go struct code generator) when
ondatra’s gnmi/oc package is regenerated.
Evidence: - OpenConfig models v5.6.0 (bundled in ondatra v0.14.1)
includes openconfig-platform-healthz.yang - The healthz model has
been in the public schema since January 2023 (revision 0.1.0) - The
generated *oc.Component struct contains fields for many augmenting
modules (e.g., openconfig-platform-cpu, openconfig-platform-fan,
openconfig-platform-transceiver) - But openconfig-platform-healthz
is conspicuously absent
Impact Analysis
Affected Code
Any test that calls gnmi.GetAll() on full component state will be affected:
File: feature/container/failover/tests/supervisor_failover/failover_test.go
Locations: L554
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/platform/tests/telemetry_inventory_test/telemetry_inventory_test.go
Locations: L381, L948, L1038
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/platform/tests/breakout_subscription_test/breakout_subscription_test.go
Locations: L506, L553
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/interface/singleton/tests/singleton_with_breakouts/singleton_with_breakouts_test.go
Locations: L134, L177
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/gnoi/system/tests/complete_chassis_reboot/complete_chassis_reboot_test.go
Location: L115, L228
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: internal/components/components.go
Location: L52, L76
Pattern: gnmi.GetAll[*oc.Component](t, dut, gnmi.OC().ComponentAny().State())
Consequences
- Silent Data Loss: Healthz telemetry data from DUTs is silently dropped during unmarshal. Tests cannot access component health status.
- Error Flooding: Multiple unmarshal errors appear in test logs, reducing signal-to-noise ratio and making it harder to diagnose actual issues.
- Schema Compliance Gap: The generated Go structs do not fully represent the OpenConfig platform schema, breaking strict schema validation.
- Impossible to Query Healthz: No typed path available to query healthz data via ygnmi (e.g., gnmi.OC().Component(name).Healthz().State().Status().State() doesn’t exist).
Requested Fix
Add openconfig-platform-healthz.yang to the YANG model set used for code generation in ondatra.
Expected Outcome
The regenerated *oc.Component struct should include:
type Component struct {
// ... existing fields ...
Healthz *Component_Healthz path:"healthz" module:"openconfig-pl // ... rest of fields ... type Component_Healthz struct { State *Component_Healthz_State path:"state" module:"openconfig-platform-healthz"`
}
}
type Component_Healthz_State struct {
Status E_ComponentHealthzStatus path:"status" module:"openconfig-platform-hea LastUnhealthy *uint64 path:"last-unhealthy" module:"openconfig-plat
UnhealthyCount *uint64 `path:"unhealthy-count" module:"openconfig-pla
}
type E_ComponentHealthzStatus int32
const (
E_ComponentHealthzStatus_UNSPECIFIED E_ComponentHealthzStatus = iota
E_ComponentHealthzStatus_HEALTHY
E_ComponentHealthzStatus_UNHEALTHY
)
This would allow: -All healthz leaves to unmarshal without error - Typed ygnmi paths: gnmi.OC().Component(name).Healthz().State().Status().State() - Full schema compliance with OpenConfig models v5.6.0
Repository: github.com/openconfig/ondatra
Affected Version: v0.14.1 (current latest, released Feb 18, 2026)
Severity: Medium — causes silent data loss and unmarshal error floods
Date: March 26, 2026
Summary
The openconfig-platform-healthz YANG model augments the /components/component
hierarchy with a healthz container that includes three leaves for monitoring
component health status. This model has been part of the OpenConfig public
schema since January 2023. However, the generated *oc.Component Go struct
in ondatra v0.14.1/gnmi/oc/structs-0.go does not contain a Healthz
field, causing unmarshal errors and silent data loss in any test that reads full
component state telemetry from a DUT that advertises healthz data.
Problem Details
YANG Model Definition
The openconfig-platform-healthz YANG model defines the following aug-
mentation:
YANG Path : /components/component/healthz/state/status
Type : enum
Description : Component health status: UNSPECIFIED, HEALTHY, UNHEALTHY
YANG Path : /components/component/healthz/state/last-unhealthy
Type : timeticks64
Description : Nanoseconds since Unix epoch when component was last unhealthy
YANG Path : /components/component/healthz/state/unhealthy-count
Type : uint64
Description : Counter for number of times component transitioned to unhealthy state
Source: openconfig-platform-healthz.yang
Module Revision: 2023-04-11 (v0.1.1)
YANG Augmentation:
module openconfig-platform-healthz {
// ... namespace and imports ...
augment "/oc-platform:components/oc-platform:component" {
description "Augment healthz information into the /components/component hierarchy.";
uses platform-health-top;
}
grouping platform-health-top {
container healthz {
container state {
config false;
leaf status {
type enumeration { enum UNSPECIFIED; enum HEALTHY; enum UNHEALTHY; }
oc-ext:telemetry-on-change;
}
leaf last-unhealthy { type oc-types:timeticks64; }
leaf unhealthy-count { type uint64; }
}
}
}
}
Generated Go Struct Issue
The *oc.Component struct in ondatra v0.14.1/gnmi/oc/structs-0.go is missing the Healthz field:
type Component struct {
AllocatedPower *uint32
path:"state/allocated-power" ...Backplane *Component_Backplane
path:"backplane" ...BaseMacAddress *string
path:"state/base-mac-address" ...BootLoader *Component_BootLoader
path:"boot-loader" ...BootTime *uint64
path:"state/boot-time" ...Chassis *Component_Chassis
path:"chassis" ...// ... other fields ...
HardwareVersion *string
path:"state/hardware-version" ...Id *string
path:"state/id" ...// � HEALTHZ FIELD IS MISSING HERE
InstallComponent *string
path:"state/install-component" ...// ... other fields continue ...
}
Runtime Error Messages
When a DUT advertises healthz state data and a test calls gnmi.GetAll(t,
dut, gnmi.OC().ComponentAny().State()), the following errors appear:
Unmarshal string_val:"UNHEALTHY" into origin:"openconfig"
elem:{name:"components"}
elem:{name:"component" key:{key:"name" value:"CHASSIS0"}}
elem:{name:"healthz"} elem:{name:"state"} elem:{name:"status"}:
path "/components/component[name=CHASSIS0]/healthz/state/status" is invalid and cannot be ma
to a generated GoStruct field: rpc error: code = InvalidArgument desc = no match found in *o
for path elem:{name:"healthz"} elem:{name:"state"} elem:{name:"status"}
Unmarshal uint_val:1774337554888000000 into origin:"openconfig"
elem:{name:"components"}
elem:{name:"component" key:{key:"name" value:"CHASSIS0"}}
elem:{name:"healthz"} elem:{name:"state"} elem:{name:"last-unhealthy"}:
path "/components/component[name=CHASSIS0]/healthz/state/last-unhealthy" is invalid and cann
to a generated GoStruct field: rpc error: code = InvalidArgument desc = no match found in *o
for path elem:{name:"healthz"} elem:{name:"state"} elem:{name:"last-unhealthy"}
Unmarshal uint_val:1 into origin:"openconfig"
elem:{name:"components"}
elem:{name:"component" key:{key:"name" value:"CHASSIS0"}}
elem:{name:"healthz"} elem:{name:"state"} elem:{name:"unhealthy-count"}:
path "/components/component[name=CHASSIS0]/healthz/state/unhealthy-count" is invalid and can
to a generated GoStruct field: rpc error: code = InvalidArgument desc = no match found in *o
for path elem:{name:"healthz"} elem:{name:"state"} elem:{name:"unhealthy-count"}
These errors appear once per healthz leaf per component, flooding test
output and making it difficult to diagnose real issues.
Root Cause Analysis
The openconfig-platform-healthz.yang model is not being included in the set of YANG models fed to ygen (the Go struct code generator) when
ondatra’s gnmi/oc package is regenerated.
Evidence: - OpenConfig models v5.6.0 (bundled in ondatra v0.14.1)
includes openconfig-platform-healthz.yang - The healthz model has
been in the public schema since January 2023 (revision 0.1.0) - The
generated *oc.Component struct contains fields for many augmenting
modules (e.g., openconfig-platform-cpu, openconfig-platform-fan,
openconfig-platform-transceiver) - But openconfig-platform-healthz
is conspicuously absent
Impact Analysis
Affected Code
Any test that calls gnmi.GetAll() on full component state will be affected:
File: feature/container/failover/tests/supervisor_failover/failover_test.go
Locations: L554
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/platform/tests/telemetry_inventory_test/telemetry_inventory_test.go
Locations: L381, L948, L1038
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/platform/tests/breakout_subscription_test/breakout_subscription_test.go
Locations: L506, L553
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/interface/singleton/tests/singleton_with_breakouts/singleton_with_breakouts_test.go
Locations: L134, L177
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: feature/gnoi/system/tests/complete_chassis_reboot/complete_chassis_reboot_test.go
Location: L115, L228
Pattern: gnmi.GetAll(t, dut, gnmi.OC().ComponentAny().State())
File: internal/components/components.go
Location: L52, L76
Pattern: gnmi.GetAll[*oc.Component](t, dut, gnmi.OC().ComponentAny().State())
Consequences
Requested Fix
Add openconfig-platform-healthz.yang to the YANG model set used for code generation in ondatra.
Expected Outcome
The regenerated *oc.Component struct should include:
type Component struct {
// ... existing fields ...
Healthz *Component_Healthz
path:"healthz" module:"openconfig-pl // ... rest of fields ... type Component_Healthz struct { State *Component_Healthz_Statepath:"state" module:"openconfig-platform-healthz"`}
}
type Component_Healthz_State struct {
Status E_ComponentHealthzStatus
path:"status" module:"openconfig-platform-hea LastUnhealthy *uint64path:"last-unhealthy" module:"openconfig-platUnhealthyCount *uint64 `path:"unhealthy-count" module:"openconfig-pla
}
type E_ComponentHealthzStatus int32
const (
E_ComponentHealthzStatus_UNSPECIFIED E_ComponentHealthzStatus = iota
E_ComponentHealthzStatus_HEALTHY
E_ComponentHealthzStatus_UNHEALTHY
)
This would allow: -All healthz leaves to unmarshal without error - Typed ygnmi paths: gnmi.OC().Component(name).Healthz().State().Status().State() - Full schema compliance with OpenConfig models v5.6.0