amir20/dozzle · error
failed to create config file
Error message
failed to create config file: %w
What it means
The handler opens h.configPath with os.Create after ensuring ./data exists. If the file cannot be created or truncated (permissions, missing parent dir, path is a directory, disk full), the error is wrapped with this message and the config is not saved.
Solutions
- Check the wrapped syscall error (EACCES/EISDIR/ENOENT) for the cause
- Ensure the parent directory of configPath exists and is writable (mkdir -p on its dir)
- If configPath is a directory, change it to a file path
- Run the process with a user that has write access to the path, or mount a writable volume
Example fix
// before --notification-config ./data/notifications/ # os.Create on a directory fails // after --notification-config ./data/notifications.yml
Defensive patterns
Strategy: try-catch
Validate before calling
dir := filepath.Dir(h.configPath)
if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
os.MkdirAll(dir, 0755)
} Try / catch
file, err := os.Create(h.configPath)
if err != nil {
if errors.Is(err, fs.ErrPermission) || errors.Is(err, syscall.EISDIR) { /* fix path/permissions */ }
return err
} Prevention
- Point configPath at a file, never a directory
- Create the parent directory of configPath, not just ./data
- Ensure the process user can write to the config location
When it happens
Trigger: os.Create(h.configPath) failing: no write permission in the target directory, configPath points at an existing directory, parent directory doesn't exist (MkdirAll only covers ./data, not configPath's dir), or filesystem full/read-only.
Common situations: configPath set to a subdirectory like ./data/notifications/ (a dir) instead of a file; running as an unprivileged user without rights to a custom --config path; custom configPath outside ./data whose parents were never created.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- failed to create data directory
- failed to save config
- container actions are not enabled
- creating subscription
- failed to write agent address file
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/734ef56e766adece.
Report an issue: GitHub.
Appendix: source
Thrown at internal/support/cli/agent_command.go:63
func (h *persistingNotificationHandler) GetNotificationStats() []types.SubscriptionStats {
return h.manager.GetNotificationStats()
}
func (h *persistingNotificationHandler) HandleNotificationConfig(subscriptions []types.SubscriptionConfig, dispatchers []types.DispatcherConfig) error {
// Update the manager
if err := h.manager.HandleNotificationConfig(subscriptions, dispatchers); err != nil {
return err
}
// Save to disk
if err := os.MkdirAll("./data", 0755); err != nil {
return fmt.Errorf("failed to create data directory: %w", err)
}
file, err := os.Create(h.configPath)
if err != nil {
return fmt.Errorf("failed to create config file: %w", err)
}
defer file.Close()
if err := h.manager.WriteConfig(file); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
log.Debug().Str("path", h.configPath).Msg("Saved notification config to disk")
return nil
}
// SetCloudStreamLogs applies the hub's log-streaming choice to this agent's own
// cloud client. The agent streams its logs to cloud itself rather than through
// the hub, so without this a user who turned streaming off saw it stop on the
// hub while every agent kept sending.
func (h *persistingNotificationHandler) SetCloudStreamLogs(enabled *bool) {
cc := h.cloudConfig.Load()
if cc == nil {View on GitHub (pinned to d9463cbe21)