gotify/server · error
error while reading directory %s
Error message
error while reading directory %s
What it means
loadPlugins reads the plugin directory with os.ReadDir before scanning for .so files. If the directory cannot be read (does not exist, is not a directory, or lacks permissions), the error is wrapped as 'error while reading directory %s' — note the format verb receives the error, so the message reads 'error while reading directory <err text>'.
Source
Thrown at plugin/manager.go:218
}
type pluginFileLoadError struct {
Filename string
UnderlyingError error
}
func (c pluginFileLoadError) Error() string {
return fmt.Sprintf("error while loading plugin %s: %s", c.Filename, c.UnderlyingError)
}
func (m *Manager) loadPlugins(directory string) error {
if directory == "" {
return nil
}
pluginFiles, err := os.ReadDir(directory)
if err != nil {
return fmt.Errorf("error while reading directory %s", err)
}
for _, f := range pluginFiles {
if f.IsDir() {
continue
}
name := f.Name()
if strings.HasPrefix(name, ".") {
continue
}
pluginPath := filepath.Join(directory, "./", name)
log.Info().Str("path", pluginPath).Msg("Loading plugin")
pRaw, err := plugin.Open(pluginPath)
if err != nil {
return pluginFileLoadError{name, err}
}View on GitHub (pinned to 14bfc25627)
Solutions
- Verify the configured plugin directory path is correct and exists
- Create the directory (mkdir -p <dir>) before starting the server
- Fix filesystem permissions so the server user can read the directory
- If no plugins are wanted, leave the directory setting empty instead of pointing to a nonexistent path
Example fix
// before (docker-compose) volumes: [] # plugin dir never mounted // after volumes: - ./plugins:/app/data/plugins
Defensive patterns
Strategy: validation
Validate before calling
dir := cfg.PluginDir
if dir != "" {
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
return fmt.Errorf("plugin dir %q missing or not a directory", dir)
}
} Try / catch
mgr, err := plugin.NewManager(dir, ...)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) {
log.Fatalf("cannot read plugin dir: %v", pe)
}
return err
} Prevention
- Create the plugin directory at deployment time (mkdir -p)
- Mount the plugin volume correctly in containers
- Check directory read permissions for the server user
- Use an empty value to explicitly disable plugin loading
When it happens
Trigger: Manager creation with a pluginDir that does not exist, is a file rather than a directory, or the process lacks read permission on it; an empty directory string short-circuits to nil, so the value must be non-empty and invalid.
Common situations: Misconfigured plugin directory path in config, Docker volume not mounted, or directory removed between startup and reload.
Related errors
- plugin does not support %s
- NewGotifyPluginInstance signature mismatch, func(ctx plugin.
- unknown plugin version (unrecogninzed GetGotifyPluginInfo si
- plugin with module path %s is present at least twice
- user with id %d not found
AI-assisted analysis of gotify/server@14bfc25627 (2026-09-05).
Data as JSON: /api/errors/4631bb806b5a0047.
Report an issue: GitHub.