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

  1. Align istioctl with the mesh version (this decoder is version-sensitive by design)
  2. Re-pull the dump directly from the pod to eliminate copy corruption
  3. 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

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


AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15). Data as JSON: /api/errors/ea73f3045a94fcbd. Report an issue: GitHub.