benbjohnson/litestream · error
start directory monitor for %s: %w
Error message
start directory monitor for %s: %w
What it means
Directory monitors watch configured directories for new SQLite databases and register them with the store. When starting a monitor fails (e.g. the directory does not exist or cannot be watched), Run closes already-started monitors and the store, then returns this error naming the offending directory.
Source
Thrown at cmd/litestream/replicate.go:321
c.Server.SocketPath = c.Config.Socket.Path
c.Server.SocketPerms = c.Config.Socket.Permissions
c.Server.PathExpander = expand
c.Server.Version = Version
if err := c.Server.Start(); err != nil {
slog.Warn("failed to start control server", "error", err)
}
}
for _, entry := range watchables {
monitor, err := NewDirectoryMonitor(ctx, c.Store, entry.config, entry.dbs)
if err != nil {
for _, m := range c.directoryMonitors {
m.Close()
}
if closeErr := c.Store.Close(ctx); closeErr != nil {
slog.Error("failed to close store after monitor failure", "error", closeErr)
}
return fmt.Errorf("start directory monitor for %s: %w", entry.config.Dir, err)
}
c.directoryMonitors = append(c.directoryMonitors, monitor)
}
// Notify user that initialization is done.
for _, db := range c.Store.DBs() {
r := db.Replica
slog.Info("initialized db", "path", db.Path())
slogWith := slog.With("type", r.Client.Type(), "sync-interval", r.SyncInterval)
switch client := r.Client.(type) {
case *file.ReplicaClient:
slogWith.Info("replicating to", "path", client.Path())
case *s3.ReplicaClient:
slogWith.Info("replicating to", "bucket", client.Bucket, "path", client.Path, "region", client.Region, "endpoint", client.Endpoint)
case *gs.ReplicaClient:
slogWith.Info("replicating to", "bucket", client.Bucket, "path", client.Path)
case *abs.ReplicaClient:
slogWith.Info("replicating to", "bucket", client.Bucket, "path", client.Path, "endpoint", client.Endpoint)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check the directory path in the error exists and is readable before starting litestream
- Fix the config entry for the directory monitor (remove or correct the path)
- Ensure the volume/directory is mounted in containerized deployments before startup
- Raise fs.inotify.max_user_watches/max_user_instances if watcher limits are the cause
Example fix
// before (config) monitor: - dir: /data/dbs // after # verify path exists mkdir -p /data/dbs && litestream replicate -config litestream.yml
Defensive patterns
Strategy: validation
Validate before calling
# ensure all monitored dirs exist and are readable before start
for d in $(yq '.monitor[].dir' litestream.yml); do
[ -d "$d" ] && [ -r "$d" ] || { echo "bad monitor dir: $d" >&2; exit 1; }
done Try / catch
if err := cmd.Run(ctx); err != nil {
if strings.Contains(err.Error(), "start directory monitor") {
// extract dir from message, alert on config/volume problem
}
return err
} Prevention
- Create monitored directories before litestream starts (init containers / entrypoint scripts)
- Mount volumes before launching litestream in containers
- Check fs.inotify limits (max_user_watches) on hosts with many directories
- Keep monitor dir entries in sync with actual filesystem layout
When it happens
Trigger: Config contains a directory monitor entry (`dir:` style config); the monitored path doesn't exist, isn't readable, or the filesystem watcher cannot be initialized. `monitor.Start(ctx)` returns err at line ~321 of replicate.go.
Common situations: Typo in monitored directory path, directory created only after litestream starts, containers where the volume isn't mounted yet, inotify limits exhausted on Linux.
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/18626ee129ff6397.
Report an issue: GitHub.