Billionmail/BillionMail · error
marshal lipsync request: %w
Error message
marshal lipsync request: %w
What it means
BuildLipSyncRequest JSON-encodes the lipsync API request body before constructing the http.Request. If json.Marshal fails on the request struct, the error is wrapped as 'marshal lipsync request: %w'. This is rare for this struct (plain strings/fields), but can happen if unsupported types (channels, funcs, NaN floats) sneak into the payload.
Source
Thrown at core/internal/service/video_gen/lipsync.go:77
// DefaultLipSyncConfig returns config with API key from env.
func DefaultLipSyncConfig(outputDir string) LipSyncConfig {
return LipSyncConfig{
APIKey: os.Getenv("SYNCLABS_API_KEY"),
OutputDir: outputDir,
}
}
// BuildLipSyncRequest constructs the HTTP request for lip sync generation.
// Exported for testing without making API calls.
func BuildLipSyncRequest(cfg LipSyncConfig, req LipSyncRequest) (*http.Request, error) {
if req.Model == "" {
req.Model = "sync-1.7.1-beta"
}
body, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("marshal lipsync request: %w", err)
}
httpReq, err := http.NewRequest("POST", cfg.lipSyncBase()+lipSyncPath, bytes.NewReader(body))
if err != nil {
return nil, fmt.Errorf("create lipsync request: %w", err)
}
httpReq.Header.Set("x-api-key", cfg.APIKey)
httpReq.Header.Set("Content-Type", "application/json")
return httpReq, nil
}
// BuildLipSyncStatusRequest constructs the HTTP request to check job status.
// Exported for testing.
func BuildLipSyncStatusRequest(cfg LipSyncConfig, jobID string) (*http.Request, error) {
url := fmt.Sprintf("%s%s/%s", cfg.lipSyncBase(), lipSyncPath, jobID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped cause to identify the offending field/type in the request struct
- Remove or convert non-serializable fields (chan/func/cyclic structures) to JSON-safe types
- Add encoding:"json" tags or change unsupported field types to strings/numbers
- Test with a representative request struct to catch regressions (existing tests already cover headers/body)
Example fix
// before
type LipSyncRequest struct {
Callback func() `json:"callback"` // unsupported type
}
// after
type LipSyncRequest struct {
CallbackURL string `json:"callback_url"` Defensive patterns
Strategy: try-catch
Validate before calling
// JSON round-trip check before submitting
if b, err := json.Marshal(req); err != nil {
return fmt.Errorf("request not serializable: %w", err)
} else { _ = b } Try / catch
httpReq, err := video_gen.BuildLipSyncRequest(cfg)
if err != nil {
if strings.Contains(err.Error(), "marshal lipsync request") {
// unsupported field type in the request struct — fix struct or drop the field
return fmt.Errorf("request struct contains non-JSON types: %w", err)
}
return err
} Prevention
- Keep the lipsync request struct to JSON-safe field types (string, int, bool, slices)
- Add json struct tags explicitly for every field
- Run the existing TestBuildLipSyncRequest_* tests after changing the request struct
- Never embed funcs/chans or custom Marshalers that can fail in request payloads
When it happens
Trigger: json.Marshal(req) returns an error — req (or a nested field added to it) contains a type JSON cannot encode (e.g. chan, func, or a type with a broken MarshalJSON) or a custom MarshalJSON implementation returns an error.
Common situations: A new field with a non-serializable type was added to the lipsync request struct; a custom json.Marshaler on a nested type errors; NaN/Inf float values in dynamically-set fields.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- error marshalling project configuration: %v
- error marshalling knowledge base: %v
- error marshalling company profile: %v
- error marshalling empty site map: %v
- error marshalling site map: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/2d43ccac2edd6b81.
Report an issue: GitHub.