{"record":{"id":"41e2c8b0e3a6a21b","repo":"amir20/dozzle","slug":"failed-to-create-data-directory-w","errorCode":null,"errorMessage":"failed to create data directory: %w","messagePattern":"failed to create data directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/support/cli/agent_command.go","lineNumber":58,"sourceCode":"}\n\nfunc (h *persistingNotificationHandler) setCloudConfig(cc *notification.CloudConfig) {\n\th.cloudConfig.Store(cc)\n}\n\nfunc (h *persistingNotificationHandler) GetNotificationStats() []types.SubscriptionStats {\n\treturn h.manager.GetNotificationStats()\n}\n\nfunc (h *persistingNotificationHandler) HandleNotificationConfig(subscriptions []types.SubscriptionConfig, dispatchers []types.DispatcherConfig) error {\n\t// Update the manager\n\tif err := h.manager.HandleNotificationConfig(subscriptions, dispatchers); err != nil {\n\t\treturn err\n\t}\n\n\t// Save to disk\n\tif err := os.MkdirAll(\"./data\", 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create data directory: %w\", err)\n\t}\n\n\tfile, err := os.Create(h.configPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create config file: %w\", err)\n\t}\n\tdefer file.Close()\n\n\tif err := h.manager.WriteConfig(file); err != nil {\n\t\treturn fmt.Errorf(\"failed to save config: %w\", err)\n\t}\n\n\tlog.Debug().Str(\"path\", h.configPath).Msg(\"Saved notification config to disk\")\n\treturn nil\n}\n\n// SetCloudStreamLogs applies the hub's log-streaming choice to this agent's own\n// cloud client. The agent streams its logs to cloud itself rather than through","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/support/cli/agent_command.go#L40-L76","documentation":"After applying notification config changes in-memory, the agent CLI handler persists them under ./data, creating the directory with os.MkdirAll if needed. Failure to create ./data (permissions, read-only filesystem, path is a file) is wrapped with this message.","triggerScenarios":"os.MkdirAll(\"./data\", 0755) returning an error: parent directory not writable, a regular file named ./data exists, read-only container filesystem, or disk full.","commonSituations":"Running the agent as non-root in a container with a read-only rootfs and no volume mounted at /data; ./data pre-created by another process as a file; SELinux/AppArmor denying writes.","solutions":["Check the wrapped syscall error (EACCES/EROFS/EEXIST etc.) to identify the cause","Ensure ./data is a writable directory: mkdir -p data and chown to the process user","Mount a writable volume for the data directory when running in a container","Remove any regular file occupying the ./data path"],"exampleFix":"// before\n# container run with read-only fs, no data volume\n// after\n# docker run -v dozzle-data:/data ... (writable volume for ./data)","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(\"./data\"); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"./data exists but is not a directory\")\n}","typeGuard":null,"tryCatchPattern":"if err := h.manager.HandleNotificationConfig(subs, dispatchers); err != nil {\n    if errors.Is(err, fs.ErrPermission) { /* fix ownership / mount a volume */ }\n    return err\n}","preventionTips":["Mount a writable volume for the data directory in containers","Run the process as a user with write access to the working directory","Don't create a file named ./data; check paths in deployment scripts"],"tags":["filesystem","permissions","persistence"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}