istio/istio · error
unmarshal listener: %v
Error message
unmarshal listener: %v
What it means
Wrapped error in retrieveSortedListenerSlice (istioctl/pkg/writer/envoy/configdump/listener.go:600): a DynamicListeners entry with an ActiveState failed Any.UnmarshalTo into the v3 listener.Listener message. The code force-sets TypeUrl to v3.ListenerType before unmarshaling (the comment cites v2/v3 support), so failure means the serialized bytes are not a decodable v3 Listener — corrupt dump or proto incompatibility.
Source
Thrown at istioctl/pkg/writer/envoy/configdump/listener.go:600
}
func (c *ConfigWriter) retrieveSortedListenerSlice() ([]*listener.Listener, error) {
if c.configDump == nil {
return nil, fmt.Errorf("config writer has not been primed")
}
listenerDump, err := c.configDump.GetListenerConfigDump()
if err != nil {
return nil, fmt.Errorf("listener dump: %v", err)
}
listeners := make([]*listener.Listener, 0)
for _, l := range listenerDump.DynamicListeners {
if l.ActiveState != nil && l.ActiveState.Listener != nil {
listenerTyped := &listener.Listener{}
// Support v2 or v3 in config dump. See ads.go:RequestedTypes for more info.
l.ActiveState.Listener.TypeUrl = v3.ListenerType
err = l.ActiveState.Listener.UnmarshalTo(listenerTyped)
if err != nil {
return nil, fmt.Errorf("unmarshal listener: %v", err)
}
listeners = append(listeners, listenerTyped)
}
}
for _, l := range listenerDump.StaticListeners {
if l.Listener != nil {
listenerTyped := &listener.Listener{}
// Support v2 or v3 in config dump. See ads.go:RequestedTypes for more info.
l.Listener.TypeUrl = v3.ListenerType
err = l.Listener.UnmarshalTo(listenerTyped)
if err != nil {
return nil, fmt.Errorf("unmarshal listener: %v", err)
}
listeners = append(listeners, listenerTyped)
}
}
if len(listeners) == 0 {View on GitHub (pinned to 8dc789c5cf)
Solutions
- Align istioctl with the mesh version (this decoder is version-sensitive by design)
- Re-pull the dump directly from the pod to eliminate copy corruption
- Inspect the offending listener in the raw JSON dump to identify which filter payload fails to decode
Example fix
// before
dump, _ := os.ReadFile("listener-dump.json")
cw.Prime(dump)
err := cw.PrintListenerSummary(f) // "unmarshal listener: proto: ..."
// after: validate decode per section and report which dump is bad
if err := cw.Prime(dump); err != nil {
return fmt.Errorf("bad dump file: %w", err)
}
if err := cw.PrintListenerSummary(f); err != nil {
return fmt.Errorf("dump %s likely from incompatible version: %w", dumpPath, err)
} Defensive patterns
Strategy: try-catch
Try / catch
if err := cw.PrintListenerSummary(f); err != nil {
if strings.Contains(err.Error(), "unmarshal listener") {
return fmt.Errorf("listener proto undecodable (skew/corruption); refetch dump and align istioctl version: %w", err)
}
return err
} Prevention
- Version-match istioctl to the data plane before decoding dumps
- Always re-pull dumps from the pod when decode errors appear
- Preserve dump bytes exactly (no text-mode transforms) in CI artifacts
When it happens
Trigger: A dynamic listener whose ActiveState.Listener payload fails protobuf decode: dumps from an Envoy whose Listener proto is incompatible with the istioctl build's go-control-plane, or bytes corrupted in transit/storage. Static listeners take the parallel path at listener.go:613.
Common situations: Version skew between istioctl and the data plane; config dumps copied between environments through lossy tooling; experimental Envoy builds emitting changed listener fields.
Related errors
- failed to retrieve TypedExtensionConfig: %v
- listener dump: %v
- failed to marshal listeners: %v
- config writer has not been primed
- no listeners found
AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15).
Data as JSON: /api/errors/ea73f3045a94fcbd.
Report an issue: GitHub.