Billionmail/BillionMail · error

error marshalling prompt config: %v

Error message

error marshalling prompt config: %v

What it means

ModifyPrompt serializes the updated PromptConfig with json.Marshal before writing it to prompt_config.json. This error is returned if marshalling fails. For a simple struct of strings/ints this is nearly impossible at runtime (only channels, funcs, or cycles break json.Marshal), so seeing it usually signals a schema change that added an unsupported field type to PromptConfig.

Source

Thrown at core/internal/service/askai/project.go:830

// ModifyPrompt updates the prompt configuration for a given domain.
// It reads the existing prompt configuration, modifies the specified fields, and saves the updated configuration back to the file.
// If the prompt is empty, it will not be updated.
func ModifyPrompt(Domain string, Prompt string) error {
	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"`

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Check the wrapped error for 'json: unsupported type: ...' to find the offending field type
  2. Tag non-serializable fields with json:"-" so they are excluded from marshalling
  3. Implement MarshalJSON on the offending type, or store it as a plain serializable value
  4. Keep PromptConfig limited to JSON-safe types (string, int, bool, slices, nested structs)

Example fix

// before
type PromptConfig struct {
	Prompt     string        `json:"prompt"`
	UpdateHook func()        `json:"update_time"` // unsupported type
}

// after
type PromptConfig struct {
	Prompt     string        `json:"prompt"`
	UpdateTime int64         `json:"update_time"`
	UpdateHook func()        `json:"-"` // excluded from JSON
}
Defensive patterns

Strategy: validation

Validate before calling

// check PromptConfig is JSON-serializable before saving
func promptConfigIsSerializable(cfg PromptConfig) bool {
	b, err := json.Marshal(cfg)
	return err == nil && b != nil
}
// usage:
if !promptConfigIsSerializable(config) {
	log.Fatal("PromptConfig contains non-JSON-serializable fields")
}

Try / catch

if err := ModifyPrompt(domain, prompt); err != nil {
	if strings.Contains(err.Error(), "unsupported type") {
		log.Printf("PromptConfig has non-serializable field: %v", err)
		// fix struct tags before retrying
	}
	return err
}

Prevention

When it happens

Trigger: A struct type inside PromptConfig (or a field added to it) that json.Marshal cannot encode — e.g. a func, channel, or a cyclic pointer structure — followed by ModifyPrompt(domain, prompt).

Common situations: A developer added a custom field (e.g. a logger interface or callback) to PromptConfig without a json:'-' tag or MarshalJSON implementation, then tried to save the prompt.

Related errors


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