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, nil

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Check the wrapped MarshalIndent error for the offending field name/type on PromptConfig.
  2. Remove or serialize (as string/ID) any unsupported fields added to PromptConfig.
  3. Fix error paths in any custom MarshalJSON on PromptConfig or its field types.
  4. 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

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


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