containerd/containerd · error
cni network conf monitor error: %w
Error message
cni network conf monitor error: %w
What it means
criService.Run starts a cniNetConfSyncer loop per CNI network config monitor (flannel and default networks); if any syncLoop exits with an error, Run tears down the entire CRI service and returns this wrapped error, last in priority after event monitor and stream server errors. It means the CNI network configuration watching/synchronization loop failed, so pod networking config can no longer be kept in sync.
Source
Thrown at internal/cri/server/service.go:396
}
// If the error is set above, err from channel must be nil here, because
// the channel is supposed to be closed. Or else, we wait and set it.
if err := <-eventMonitorErrCh; err != nil {
eventMonitorErr = err
}
log.L.Info("Event monitor stopped")
if err := <-streamServerErrCh; err != nil {
streamServerErr = err
}
log.L.Info("Stream server stopped")
if eventMonitorErr != nil {
return fmt.Errorf("event monitor error: %w", eventMonitorErr)
}
if streamServerErr != nil {
return fmt.Errorf("stream server error: %w", streamServerErr)
}
if cniNetConfMonitorErr != nil {
return fmt.Errorf("cni network conf monitor error: %w", cniNetConfMonitorErr)
}
return nil
}
// Close stops the CRI service.
// TODO(random-liu): Make close synchronous.
func (c *criService) Close() error {
log.L.Info("Stop CRI service")
for name, h := range c.cniNetConfMonitor {
if err := h.stop(); err != nil {
log.L.WithError(err).Errorf("failed to stop cni network conf monitor for %s", name)
}
}
c.eventMonitor.Stop()
if c.statsCollector != nil {
c.statsCollector.Stop()
}
if err := c.streamServer.Stop(); err != nil {View on GitHub (pinned to 4246446a2b)
Solutions
- Check the wrapped inner error and which syncer name was logged at startup ('Start cni network conf syncer for %s') to identify the failing network.
- Verify the CNI config directory (/etc/cni/net.d) exists, is readable by containerd, and contains valid .conflist/.conf JSON (run jq against each file).
- Reinstall or repair the CNI network plugin (e.g. flannel/calico manifests) so its config files and subnet env are regenerated.
- Check inotify limits (fs.inotify.max_user_watches) if the inner error indicates watch creation failure.
- Restart containerd after fixing the CNI config so the syncers restart cleanly.
Example fix
// before: malformed CNI config /etc/cni/net.d/10-flannel.conflist (truncated JSON) // after: restore a valid conflist or remove the broken file, then sudo systemctl restart containerd
Defensive patterns
Strategy: validation
Validate before calling
// before starting containerd, sanity-check CNI config dir
import (
"encoding/json"
"os"
"path/filepath"
)
func validateCNIConfDir(dir string) error {
if _, err := os.Stat(dir); err != nil {
return fmt.Errorf("CNI conf dir %s missing/unreadable: %w", dir, err)
}
files, _ := filepath.Glob(filepath.Join(dir, "*.conf*"))
for _, f := range files {
b, err := os.ReadFile(f)
if err != nil {
return err
}
if !json.Valid(b) {
return fmt.Errorf("malformed CNI config: %s", f)
}
}
return nil
} Prevention
- Validate every file in /etc/cni/net.d parses as JSON before deploying node changes.
- Ensure CNI plugin uninstallers don't delete the conf directory out from under containerd.
- Keep directory permissions readable by the containerd user (root:root 0644/0755).
- Raise fs.inotify.max_user_watches on nodes with many watched config dirs.
- After any CNI plugin install/upgrade, restart containerd and confirm syncer startup logs appear.
When it happens
Trigger: h.syncLoop() in the cniNetConfSyncer returns non-nil: watching the CNI conf directory (e.g. /etc/cni/net.d) fails (inotify errors, directory missing), reading/parsing a CNI network config file fails, or the syncer's context is cancelled with an error.
Common situations: /etc/cni/net.d removed or unreadable on the node (CNI plugin files deleted by a broken uninstall); malformed CNI .conflist written by a network plugin installer; permission problems after host hardening; flannel syncer failing on nodes where the flannel subnet env file is missing.
Related errors
- `cni.bin_dir` and `cni.bin_dirs` cannot be set at the same t
- failed to find network info for sandbox %q
- `mirrors` cannot be set when `config_path` is provided
- `default_runtime_name` is empty
- `privileged_without_host_devices_all_devices_allowed` requir
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/76cc05720034fa3d.
Report an issue: GitHub.