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

  1. Verify the domain directory PRODUCT_CONFIG_PATH/<Domain> exists and create it: os.MkdirAll(path, os.ModePerm) before WriteFile
  2. Check directory permissions (ls -ld) and chown/chmod so the process user can write
  3. Ensure the volume/filesystem is writable (not read-only mount, not out of disk: df -h)
  4. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/5cf52034cf75ab19. Report an issue: GitHub.