{"record":{"id":"d1f765f53d8a3d0d","repo":"Billionmail/BillionMail","slug":"error-marshalling-prompt-config-v","errorCode":null,"errorMessage":"error marshalling prompt config: %v","messagePattern":"error marshalling prompt config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/askai/project.go","lineNumber":830,"sourceCode":"// ModifyPrompt updates the prompt configuration for a given domain.\n// It reads the existing prompt configuration, modifies the specified fields, and saves the updated configuration back to the file.\n// If the prompt is empty, it will not be updated.\nfunc ModifyPrompt(Domain string, Prompt string) error {\n\tconfig, err := GetPrompt(Domain)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting prompt config: %v\", err)\n\t}\n\n\t// Update the prompt configuration\n\tif Prompt != \"\" {\n\t\tconfig.Prompt = Prompt\n\t}\n\n\tconfig.UpdateTime = public.GetNowTime()\n\tfilename := fmt.Sprintf(PRODUCT_CONFIG_PATH+\"/%s/prompt_config.json\", Domain)\n\tdata, err := json.Marshal(config)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling prompt config: %v\", err)\n\t}\n\terr = os.WriteFile(filename, data, 0644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error saving prompt config file: %v\", err)\n\t}\n\treturn nil\n}\n\ntype BotResponse struct {\n\tData   BotData `json:\"data\"`\n\tMsg    string  `json:\"msg\"`\n\tStatus bool    `json:\"status\"`\n}\n\ntype BotData struct {\n\tDescription   string       `json:\"description\"`\n\tDomain        string       `json:\"domain\"`\n\tMarkdown      string       `json:\"markdown\"`","sourceCodeStart":812,"sourceCodeEnd":848,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/askai/project.go#L812-L848","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the wrapped error for 'json: unsupported type: ...' to find the offending field type","Tag non-serializable fields with json:\"-\" so they are excluded from marshalling","Implement MarshalJSON on the offending type, or store it as a plain serializable value","Keep PromptConfig limited to JSON-safe types (string, int, bool, slices, nested structs)"],"exampleFix":"// before\ntype PromptConfig struct {\n\tPrompt     string        `json:\"prompt\"`\n\tUpdateHook func()        `json:\"update_time\"` // unsupported type\n}\n\n// after\ntype PromptConfig struct {\n\tPrompt     string        `json:\"prompt\"`\n\tUpdateTime int64         `json:\"update_time\"`\n\tUpdateHook func()        `json:\"-\"` // excluded from JSON\n}","handlingStrategy":"validation","validationCode":"// check PromptConfig is JSON-serializable before saving\nfunc promptConfigIsSerializable(cfg PromptConfig) bool {\n\tb, err := json.Marshal(cfg)\n\treturn err == nil && b != nil\n}\n// usage:\nif !promptConfigIsSerializable(config) {\n\tlog.Fatal(\"PromptConfig contains non-JSON-serializable fields\")\n}","typeGuard":null,"tryCatchPattern":"if err := ModifyPrompt(domain, prompt); err != nil {\n\tif strings.Contains(err.Error(), \"unsupported type\") {\n\t\tlog.Printf(\"PromptConfig has non-serializable field: %v\", err)\n\t\t// fix struct tags before retrying\n\t}\n\treturn err\n}","preventionTips":["Keep PromptConfig limited to JSON-safe types; tag helpers with json:\"-\"","Add a unit test that marshals a fully-populated PromptConfig","Run `go vet` and marshal tests whenever the struct changes","Avoid embedding interfaces, funcs, or channels in persisted config structs"],"tags":["json","marshal","go","config"],"backgroundTag":"json-marshal-unsupported-type","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}