{"record":{"id":"775fd3c527c4e649","repo":"hashicorp/nomad","slug":"failed-to-detect-cni-conf-files-v","errorCode":null,"errorMessage":"failed to detect CNI conf files: %v","messagePattern":"failed to detect CNI conf files: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/fingerprint/cni.go","lineNumber":38,"sourceCode":"\tlogger hclog.Logger\n}\n\nfunc NewCNIFingerprint(logger hclog.Logger) Fingerprint {\n\treturn &CNIFingerprint{logger: logger}\n}\n\nfunc (f *CNIFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintResponse) error {\n\tconfDir := req.Config.CNIConfigDir\n\tnetworks := map[string]struct{}{}\n\tif _, err := os.Stat(confDir); os.IsNotExist(err) {\n\t\tf.logger.Debug(\"CNI config dir is not set or does not exist, skipping\", \"cni_config_dir\", confDir)\n\t\tresp.Detected = false\n\t\treturn nil\n\t}\n\n\tfiles, err := libcni.ConfFiles(confDir, []string{\".conf\", \".conflist\", \".json\"})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to detect CNI conf files: %v\", err)\n\t}\n\n\tfor _, confFile := range files {\n\t\tif strings.HasSuffix(confFile, \".conflist\") {\n\t\t\tconfList, err := libcni.ConfListFromFile(confFile)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to load CNI config list file %s: %v\", confFile, err)\n\t\t\t}\n\t\t\tif _, ok := networks[confList.Name]; ok {\n\t\t\t\tf.logger.Warn(\"duplicate CNI config names found, ignoring file\", \"name\", confList.Name, \"file\", confFile)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnetworks[confList.Name] = struct{}{}\n\t\t} else {\n\t\t\tconf, err := libcni.ConfFromFile(confFile)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to load CNI config file %s: %v\", confFile, err)\n\t\t\t}","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/fingerprint/cni.go#L20-L56","documentation":"The CNI fingerprinter calls libcni.ConfFiles on the configured CNI config directory (client config cni_config_dir) to enumerate .conf/.conflist/.json network definitions. This error means libcni.ConfFiles itself failed - distinct from the directory not existing (which is handled and just skips detection). ConfFiles fails when the path exists but is not a directory, or when reading it errors (permissions, I/O).","triggerScenarios":"client config cni_config_dir points to a path that exists (os.Stat succeeded) but is a regular file, a symlink to a non-directory, or cannot be read by the Nomad agent user (permission denied); libcni.ConfFiles returns the underlying os error which is wrapped here.","commonSituations":"cni_config_dir misconfigured to point at a file (e.g. the binary or a conf file itself) instead of a directory; directory owned by root with restrictive permissions while Nomad runs as an unprivileged user; directory removed/replaced with a file after client start.","solutions":["Verify cni_config_dir points to a real directory: 'ls -ld /opt/cni/config' (or your configured path).","Fix ownership/permissions so the Nomad agent user can read it (e.g. chmod/chown the directory).","Correct the client config if it points at a file; restart the Nomad client after fixing.","Ensure the path is not a broken or wrong symlink target."],"exampleFix":"HCL\n# before\nclient {\n  cni_config_dir = \"/opt/cni/bin/myconf.conflist\"  # a file, not a dir\n}\n# after\nclient {\n  cni_config_dir = \"/opt/cni/net.d\"  # existing, readable directory\n}\n# then: sudo chown nomad:nomad /opt/cni/net.d && sudo systemctl restart nomad","handlingStrategy":"validation","validationCode":"// caller-side preflight before relying on CNI fingerprint\nconfDir := cfg.Client.CNIConfigDir\nif fi, err := os.Stat(confDir); err != nil {\n    return fmt.Errorf(\"CNI config dir %q unreadable: %w\", confDir, err)\n} else if !fi.IsDir() {\n    return fmt.Errorf(\"CNI config dir %q is not a directory\", confDir)\n}\n// also ensure readability: os.ReadDir(confDir) as a dry run","typeGuard":null,"tryCatchPattern":"if err := fingerprintErr; err != nil {\n    if strings.Contains(err.Error(), \"failed to detect CNI conf files\") {\n        return fmt.Errorf(\"check cni_config_dir points to an existing, readable DIRECTORY owned by the nomad user: %w\", err)\n    }\n    return err\n}","preventionTips":["Point cni_config_dir at a directory (e.g. /opt/cni/net.d), never a file, and never the plugins bin dir.","Ensure the Nomad agent user can read/traverse the directory (chown/chmod after provisioning).","Include CNI config dir setup in the same provisioning tooling that installs CNI plugins.","Restart the Nomad client after changing the directory's location or permissions."],"tags":["cni","fingerprint","nomad","config-misconfiguration","permissions"],"backgroundTag":"cni-config-dir-invalid","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}