cilium/cilium · error
missing snapshot
Error message
missing snapshot
What it means
ConstructVersionMap on a ciliumSnapshot returns the sentinel error 'missing snapshot' when the receiver w is nil. The version map is needed by the go-control-plane cache to compute resource versions; a nil snapshot has none. Callers use this as an explicit guard rather than panicking on a nil dereference.
Source
Thrown at pkg/envoy/xdsnew/cache.go:131
}
out := make(map[string]cache_types.Resource, len(resources))
for name, resource := range resources {
out[name] = resource.Resource
}
return out
}
func (w *ciliumSnapshot) GetResourcesAndTTL(typeURL string) map[string]cache_types.ResourceWithTTL {
group, ok := w.Resources[typeURL]
if !ok {
return nil
}
return group.Items
}
func (w *ciliumSnapshot) ConstructVersionMap() error {
if w == nil {
return fmt.Errorf("missing snapshot")
}
if w.VersionMap != nil {
return nil
}
w.VersionMap = make(map[string]map[string]string, len(w.Resources))
for typeURL, group := range w.Resources {
if len(group.Items) == 0 {
continue
}
w.VersionMap[typeURL] = make(map[string]string, len(group.Items))
for name, resource := range group.Items {
marshaledResource, err := cache.MarshalResource(resource.Resource)
if err != nil {
return err
}
w.VersionMap[typeURL][name] = cache.HashResource(marshaledResource)
}View on GitHub (pinned to ac7b90affa)
Solutions
- Verify the node ID used to fetch the snapshot exists in the snapshot cache (SetSnapshot was called for it).
- Check for races where RemoveSnapshot/eviction runs while the snapshot is still being used; serialize cache lifecycle operations.
- Add a nil check before calling ConstructVersionMap in custom code built around ciliumSnapshot.
- If this occurs inside stock Cilium flows, capture logs and file an issue — a nil snapshot reaching ConstructVersionMap indicates a cache lifecycle bug.
Example fix
// before
err := snapshot.ConstructVersionMap()
// after
if snapshot == nil {
return fmt.Errorf("no snapshot available for node")
}
err := snapshot.ConstructVersionMap() Defensive patterns
Strategy: type-guard
Type guard
func snapshotReady(s cache.ResourceSnapshot) bool {
cs, ok := s.(*ciliumSnapshot)
return ok && cs != nil
} Try / catch
if err := w.ConstructVersionMap(); err != nil {
if err.Error() == "missing snapshot" {
// node has no snapshot; skip response or SetSnapshot first
return cache.ErrNoSnapshot
}
return err
} Prevention
- Always SetSnapshot for a node ID before serving its resources.
- Guard lookups: treat nil snapshot results as 'no snapshot' rather than invoking methods.
- Serialize snapshot create/remove against consumers to avoid use-after-eviction races.
When it happens
Trigger: Calling ConstructVersionMap on a nil *ciliumSnapshot — e.g. a snapshot lookup in the cache returned nil (unknown node, removed cache entry) and the code still invoked ConstructVersionMap on it.
Common situations: xDS clients requesting resources for node IDs that were never set or already evicted from the snapshot cache; races where a snapshot is deleted between fetch and use; tests constructing cache responses for nonexistent proxies.
Related errors
- nil snapshot
- Envoy: Could not validate Listener %s: %w
- error validating generated NetworkPolicy for %d/%s: %w
- generated ADS snapshot is inconsistent: %w
- mismatched %q reference and resource lengths: len(%v) != %d
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/6fa6cdd5f0a078bf.
Report an issue: GitHub.