Billionmail/BillionMail · error
error saving prompt config file: %v
Error message
error saving prompt config file: %v
What it means
After successfully marshalling the config, ModifyPrompt writes it with os.WriteFile to PRODUCT_CONFIG_PATH/<Domain>/prompt_config.json. This error wraps the os.WriteFile failure — the file could not be created or written (missing directory, permissions, read-only filesystem, disk full). The config update is not saved.
Source
Thrown at core/internal/service/askai/project.go:834
config, err := GetPrompt(Domain)
if err != nil {
return fmt.Errorf("error getting prompt config: %v", err)
}
// Update the prompt configuration
if Prompt != "" {
config.Prompt = Prompt
}
config.UpdateTime = public.GetNowTime()
filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/prompt_config.json", Domain)
data, err := json.Marshal(config)
if err != nil {
return fmt.Errorf("error marshalling prompt config: %v", err)
}
err = os.WriteFile(filename, data, 0644)
if err != nil {
return fmt.Errorf("error saving prompt config file: %v", err)
}
return nil
}
type BotResponse struct {
Data BotData `json:"data"`
Msg string `json:"msg"`
Status bool `json:"status"`
}
type BotData struct {
Description string `json:"description"`
Domain string `json:"domain"`
Markdown string `json:"markdown"`
Footer BotFooter `json:"footer"`
Icon string `json:"icon"`
Images []ImageInfo `json:"images"`
Keywords string `json:"keywords"`View on GitHub (pinned to fc36c76c05)
Solutions
- Verify the domain directory PRODUCT_CONFIG_PATH/<Domain> exists and create it: os.MkdirAll(path, os.ModePerm) before WriteFile
- Check directory permissions (ls -ld) and chown/chmod so the process user can write
- Ensure the volume/filesystem is writable (not read-only mount, not out of disk: df -h)
- Make the save atomic: write to a temp file in the same dir then os.Rename over prompt_config.json
Example fix
// before
filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/prompt_config.json", Domain)
data, err := json.Marshal(config)
if err != nil { return fmt.Errorf("error marshalling prompt config: %v", err) }
err = os.WriteFile(filename, data, 0644)
// after
filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/prompt_config.json", Domain)
if err := os.MkdirAll(filepath.Dir(filename), os.ModePerm); err != nil {
return fmt.Errorf("error creating config dir: %v", err)
}
data, err := json.Marshal(config)
if err != nil { return fmt.Errorf("error marshalling prompt config: %v", err) }
if err := os.WriteFile(filename, data, 0644); err != nil {
return fmt.Errorf("error saving prompt config file: %v", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: verify the target path is writable before ModifyPrompt
func configPathWritable(domain string) bool {
dir := filepath.Join(PRODUCT_CONFIG_PATH, domain)
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return false
}
probe := filepath.Join(dir, ".write_probe")
if err := os.WriteFile(probe, nil, 0644); err != nil {
return false
}
os.Remove(probe)
return true
} Try / catch
if err := ModifyPrompt(domain, prompt); err != nil {
if strings.Contains(err.Error(), "saving prompt config file") {
// fs issue: check disk space and permissions before retry
log.Printf("config save failed (check mount/permissions/disk): %v", err)
return fmt.Errorf("config storage unavailable: %w", err)
}
return err
} Prevention
- Always MkdirAll the target directory before os.WriteFile
- Verify volume mounts are writable in read-only container deployments
- Monitor disk space/quota on the config volume
- Use atomic writes (temp file + rename) and check the wrapped syscall (EACCES, ENOSPC, EROFS) in logs
When it happens
Trigger: Calling ModifyPrompt(domain, prompt) when PRODUCT_CONFIG_PATH/<Domain>/ does not exist (GetPrompt only creates it when the file is absent, but a stale half-deleted dir can break this), the directory is read-only, or the disk is full.
Common situations: Docker container with a read-only root filesystem and no writable volume mounted at the config path; config dir owned by root while app runs unprivileged; disk quota exceeded; parent directory removed concurrently.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- error reading project configuration file: %v
- error writing project configuration file: %v
- error writing knowledge base file: %v
- error creating company profile file: %v
- error reading company profile file: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/5cf52034cf75ab19.
Report an issue: GitHub.