{"record":{"id":"d7f151d18ac04a0c","repo":"Billionmail/BillionMail","slug":"marshal-clone-request-w","errorCode":null,"errorMessage":"marshal clone request: %w","messagePattern":"marshal clone request: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/internal/service/video_gen/voice.go","lineNumber":99,"sourceCode":"\t\tOutputDir: outputDir,\n\t}\n}\n\n// DefaultTTSOutputFormat returns WAV 44.1kHz PCM format.\nfunc DefaultTTSOutputFormat() TTSOutputFormat {\n\treturn TTSOutputFormat{\n\t\tContainer:  \"wav\",\n\t\tSampleRate: 44100,\n\t\tEncoding:   \"pcm_f32le\",\n\t}\n}\n\n// BuildCloneRequest constructs the HTTP request for voice cloning.\n// Exported for testing without making API calls.\nfunc BuildCloneRequest(cfg VoiceConfig, req VoiceCloneRequest) (*http.Request, error) {\n\tbody, err := json.Marshal(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal clone request: %w\", err)\n\t}\n\n\thttpReq, err := http.NewRequest(\"POST\", cfg.voiceBaseURL()+cartesiaClonePath, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create clone request: %w\", err)\n\t}\n\n\thttpReq.Header.Set(\"X-API-Key\", cfg.APIKey)\n\thttpReq.Header.Set(\"Cartesia-Version\", cartesiaAPIVersion)\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\treturn httpReq, nil\n}\n\n// BuildTTSRequest constructs the HTTP request for text-to-speech.\n// Exported for testing without making API calls.\nfunc BuildTTSRequest(cfg VoiceConfig, req TTSRequest) (*http.Request, error) {\n\tbody, err := json.Marshal(req)\n\tif err != nil {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/video_gen/voice.go#L81-L117","documentation":"BuildCloneRequest marshals the VoiceCloneRequest struct to JSON before constructing the Cartesia clone HTTP request; a json.Marshal failure is wrapped as 'marshal clone request: %w'. In practice json.Marshal on plain data structs is nearly impossible to fail, making this a defensive guard.","triggerScenarios":"json.Marshal(req) returns an error, which for this struct realistically only happens if a field is replaced by an unsupported type (e.g. a channel, func, or a cycle introduced via a custom MarshalJSON).","commonSituations":"Developers extending VoiceCloneRequest with unmarshalable fields (channels, funcs, cyclic pointers, or types with a broken MarshalJSON); normal runtime operation essentially never hits this path.","solutions":["Inspect any recently added fields on VoiceCloneRequest for unsupported types (chan, func, cycles) or a faulty MarshalJSON implementation","If a custom MarshalJSON was added, fix it to return valid JSON instead of an error","Validate the request payload in tests (TestBuildCloneRequest_Body covers the happy path) after schema changes"],"exampleFix":"// before\ntype VoiceCloneRequest struct {\n    Name    string `json:\"name\"`\n    Samples []byte `json:\"samples\"`\n    // Callback func() `json:\"-\"` // unmarshalable field causes this error\n}\n// after\ntype VoiceCloneRequest struct {\n    Name    string `json:\"name\"`\n    Samples []byte `json:\"samples\"`\n    Callback func() `json:\"-\"` // excluded from JSON with '-'\n}","handlingStrategy":"validation","validationCode":"func validateCloneRequest(req VoiceCloneRequest) error {\n    if req.Name == \"\" {\n        return fmt.Errorf(\"clone request requires a name\")\n    }\n    if _, err := json.Marshal(req); err != nil {\n        return fmt.Errorf(\"clone request not serializable: %w\", err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"httpReq, err := video_gen.BuildCloneRequest(cfg, req)\nif err != nil {\n    var jsonErr *json.UnsupportedTypeError\n    if errors.As(err, &jsonErr) {\n        log.Errorf(\"unmarshalable field in VoiceCloneRequest: %v\", jsonErr)\n    }\n    return err\n}","preventionTips":["Keep VoiceCloneRequest fields JSON-serializable (no chan/func fields; use json:\"-\")","Run TestBuildCloneRequest_Body after every struct change","Avoid custom MarshalJSON unless tested","Validate required fields before constructing the request"],"tags":["json","serialization","cartesia","voice-clone"],"backgroundTag":"json-marshal-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}