{"record":{"id":"7fec4be281d19d15","repo":"hashicorp/nomad","slug":"failed-to-scan-plugin-directory-q-v","errorCode":null,"errorMessage":"failed to scan plugin directory %q: %v","messagePattern":"failed to scan plugin directory %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/pluginutils/loader/init.go","lineNumber":70,"sourceCode":"\treturn mErr.ErrorOrNil()\n}\n\n// init initializes the plugin loader by compiling both internal and external\n// plugins and selecting the highest versioned version of any given plugin.\nfunc (l *PluginLoader) init(cfg *PluginLoaderConfig) (map[string]*config.PluginConfig, error) {\n\t// Create a mapping of name to config\n\tconfigMap := configMap(cfg.Configs)\n\n\t// Initialize the internal plugins\n\tinternal, err := l.initInternal(cfg.InternalPlugins, configMap)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fingerprint internal plugins: %v\", err)\n\t}\n\n\t// Scan for eligibile binaries\n\tplugins, err := l.scan()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to scan plugin directory %q: %v\", l.pluginDir, err)\n\t}\n\n\t// Fingerprint the passed plugins\n\texternal, err := l.fingerprintPlugins(plugins, configMap)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fingerprint plugins: %v\", err)\n\t}\n\n\t// Merge external and internal plugins\n\tl.plugins = l.mergePlugins(internal, external)\n\n\t// Validate that the configs are valid for the plugins\n\tcanonicalizedConfigs, err := l.validatePluginConfigs()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing plugin configurations failed: %v\", err)\n\t}\n\n\tfor i := range configMap {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/pluginutils/loader/init.go#L52-L88","documentation":"After initializing internal plugins, the loader calls scan() to walk l.pluginDir for eligible plugin binaries. If that filesystem scan fails (unreadable directory, permission denied, stat errors), init wraps the error with the plugin directory path in this message.","triggerScenarios":"PluginDir points to a nonexistent path; the process lacks read/execute permission on the directory; the path is a file, not a directory; an FS error occurs while walking entries.","commonSituations":"Container images where the plugin dir wasn't created or mounted; running the app as a non-root user after plugins were installed as root with restrictive modes; typo'd path in config; bind mount missing in Kubernetes/Docker.","solutions":["Check that the directory in the error message exists: ls <dir>.","Fix permissions: chmod/chown the directory so the process user can read and traverse it.","Correct the PluginDir value in the loader config.","In containers, ensure the plugins volume is mounted and the path is created in the image."],"exampleFix":"// before\ncfg := &PluginLoaderConfig{PluginDir: \"/opt/nomad-plugins-missing\", ...}\n\n// after\nif _, err := os.Stat(pluginDir); err != nil {\n    return fmt.Errorf(\"plugin dir unavailable: %w\", err)\n}\ncfg := &PluginLoaderConfig{PluginDir: pluginDir, ...}","handlingStrategy":"validation","validationCode":"info, err := os.Stat(cfg.PluginDir)\nif err != nil || !info.IsDir() {\n    return fmt.Errorf(\"plugin dir %q missing or not a directory\", cfg.PluginDir)\n}\nif err := unix.Access(cfg.PluginDir, unix.R_OK|unix.X_OK); err != nil {\n    return fmt.Errorf(\"plugin dir %q not readable: %w\", cfg.PluginDir, err)\n}","typeGuard":null,"tryCatchPattern":"loader, err := NewPluginLoader(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to scan plugin directory\") {\n        return fmt.Errorf(\"check plugin dir existence/permissions: %w\", err)\n    }\n    return err\n}","preventionTips":["Create the plugin directory in image/entrypoint before starting the app.","Verify volume mounts in container orchestration configs.","Run the service as a user with read+execute on the plugin dir.","Log the resolved PluginDir at startup for easier diagnosis."],"tags":["go","filesystem","permissions","plugins"],"backgroundTag":"no-such-file-or-directory","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"}