{"record":{"id":"d86df54fa33ee21a","repo":"crowdsecurity/crowdsec","slug":"plugin-at-s-does-not-exist-w","errorCode":null,"errorMessage":"plugin at %s does not exist: %w","messagePattern":"plugin at (.+?) does not exist: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csplugin/utils.go","lineNumber":101,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &unix.SysProcAttr{\n\t\tCredential: &syscall.Credential{\n\t\t\tUid: uid,\n\t\t\tGid: gid,\n\t\t},\n\t}, nil\n}\n\nfunc pluginIsValid(path string) error {\n\tvar details fs.FileInfo\n\tvar err error\n\n\t// check if it exists\n\tif details, err = os.Stat(path); err != nil {\n\t\treturn fmt.Errorf(\"plugin at %s does not exist: %w\", path, err)\n\t}\n\n\t// check if it is owned by current user\n\tcurrentUser, err := user.Current()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"while getting current user: %w\", err)\n\t}\n\tcurrentUID, err := getUID(currentUser.Username)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"while looking up the current uid: %w\", err)\n\t}\n\tstat := details.Sys().(*syscall.Stat_t)\n\tif stat.Uid != currentUID {\n\t\treturn fmt.Errorf(\"plugin at %s is not owned by user '%s'\", path, currentUser.Username)\n\t}\n\n\tmode := details.Mode()\n\tperm := uint32(mode)","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csplugin/utils.go#L83-L119","documentation":"pluginIsValid performs os.Stat on the plugin path before any security checks; if the stat fails the error is wrapped as 'plugin at %s does not exist'. The wrapped cause distinguishes ENOENT (missing) from other stat failures such as permission on a parent directory.","triggerScenarios":"loadNotificationPlugin iterates the configured plugin directory and calls pluginIsValid on a path that does not exist, has been deleted between enumeration and validation, or whose parent directory is not traversable.","commonSituations":"Configured plugin_path points to a directory or binary that was never installed; plugin binary removed after an upgrade; typo in the path; running crowdsec in a container without the plugins mounted.","solutions":["Verify the path exists on the host: ls -l <path from the error message>","Check the plugin directory setting in config and correct it (commonly /usr/lib/crowdsec/plugins/)","Reinstall the notification plugin binary; if running in a container, mount the plugins directory"],"exampleFix":"# before\ncscli -c /etc/crowdsec/config.yaml ... plugin_dir: /opt/plugins\n# after\nplugin_dir: /usr/lib/crowdsec/plugins","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(pluginPath); os.IsNotExist(err) {\n    return fmt.Errorf(\"plugin binary not installed at %s\", pluginPath)\n}","typeGuard":null,"tryCatchPattern":"if err := pluginIsValid(path); err != nil {\n    if errors.Is(err, fs.ErrNotExist) {\n        log.Fatalf(\"install the plugin binary: %v\", err)\n    }\n    return err\n}","preventionTips":["Verify plugin_dir exists and contains the binary after each deployment","Mount the plugins volume in containers before starting crowdsec","Use the documented install path (/usr/lib/crowdsec/plugins/) instead of custom locations"],"tags":["go","plugin","filesystem","missing-file"],"backgroundTag":"file-not-found","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}