Billionmail/BillionMail · error
error marshalling default prompt config: %v
Error message
error marshalling default prompt config: %v
What it means
GetPrompt fails at project.go:791 when json.MarshalIndent cannot serialize the freshly constructed default PromptConfig before writing prompt_config.json for a domain whose config file does not exist. Since the default struct is hardcoded (Prompt string + UpdateTime), this error is essentially unreachable with the stock struct; it would only fire if PromptConfig gains an unserializable field or a custom marshaler that errors. The wrapped json error is returned to the ModifyPrompt caller.
Source
Thrown at core/internal/service/askai/project.go:791
// GetPrompt retrieves the prompt configuration for a given domain from a JSON file.
// It reads the prompt configuration file and returns a PromptConfig struct.
// If the file does not exist or cannot be read, it returns an error.
func GetPrompt(Domain string) (PromptConfig, error) {
filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/prompt_config.json", Domain)
if !public.FileExists(filename) {
// If the prompt config file does not exist, return a default prompt config
// This allows the system to handle cases where the prompt configuration has not been set up
// and avoids errors when trying to read a non-existent file.
// It also allows the user to create a new prompt configuration without needing to handle file
// not found errors.
defaultPromptConfig := PromptConfig{
Prompt: "This is a default prompt. Please customize it.",
}
defaultPromptConfig.UpdateTime = public.GetNowTime()
defaultPromptJson, err := json.MarshalIndent(defaultPromptConfig, "", " ")
if err != nil {
return PromptConfig{}, fmt.Errorf("error marshalling default prompt config: %v", err)
}
err = os.WriteFile(filename, defaultPromptJson, 0644)
if err != nil {
return PromptConfig{}, fmt.Errorf("error saving default prompt config file: %v", err)
}
return defaultPromptConfig, nil
}
data, err := os.ReadFile(filename)
if err != nil {
return PromptConfig{}, fmt.Errorf("error reading prompt config file: %v", err)
}
var config PromptConfig
err = json.Unmarshal(data, &config)
if err != nil {
return PromptConfig{}, fmt.Errorf("error unmarshalling prompt config: %v", err)
}
return config, nilView on GitHub (pinned to fc36c76c05)
Solutions
- Check the wrapped MarshalIndent error for the offending field name/type on PromptConfig.
- Remove or serialize (as string/ID) any unsupported fields added to PromptConfig.
- Fix error paths in any custom MarshalJSON on PromptConfig or its field types.
- Add a unit test that marshals the default PromptConfig so regressions surface immediately.
Example fix
// before
type PromptConfig struct {
Prompt string
Hooks map[string]func(string) // not marshalable
}
// after
type PromptConfig struct {
Prompt string
HookNames []string `json:"hookNames"`
} Defensive patterns
Strategy: validation
Validate before calling
func defaultPromptSerializable() error {
cfg := PromptConfig{Prompt: "This is a default prompt. Please customize it."}
cfg.UpdateTime = public.GetNowTime()
_, err := json.MarshalIndent(cfg, "", " ")
return err
} Type guard
func isMarshalable(v any) bool {
_, err := json.Marshal(v)
return err == nil
} Try / catch
cfg, err := askai.GetPrompt(domain)
if err != nil {
var mte *json.MarshalTypeError
if errors.As(err, &mte) {
log.Printf("PromptConfig field %s (%s) not serializable — fix struct", mte.Field, mte.Type)
}
return err
} Prevention
- Keep PromptConfig free of func/chan/complex field types.
- Add a CI test that marshals the default PromptConfig so first-run init never regresses.
- Prefer plain data types (string IDs over callbacks) in config structs.
- Wrap MarshalIndent errors with the field name for faster diagnosis.
When it happens
Trigger: Calling GetPrompt(domain) (directly or via ModifyPrompt) when prompt_config.json does not exist AND the default PromptConfig value fails MarshalIndent — only possible with a modified PromptConfig containing func/chan fields, a cyclic value, or an erroring custom MarshalJSON.
Common situations: A developer extends PromptConfig with an unsupported type (e.g., a client handle or function field) and then first-run initialization on a new domain hits the default-config branch; a custom MarshalJSON added to PromptConfig returns an error.
Related errors
- error marshalling project configuration: %v
- error marshalling footer config: %v
- error unmarshalling project configuration: %v
- error marshalling knowledge base: %v
- error marshalling company profile: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/3fdf6c29a07de618.
Report an issue: GitHub.