{"record":{"id":"135bb1598636b4a3","repo":"Billionmail/BillionMail","slug":"lipsync-api-call-w","errorCode":null,"errorMessage":"lipsync API call: %w","messagePattern":"lipsync API call: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/video_gen/lipsync.go","lineNumber":119,"sourceCode":"}\n\n// SubmitLipSync submits a lip sync job and returns the job ID.\nfunc SubmitLipSync(ctx context.Context, cfg LipSyncConfig, audioURL, videoURL string) (string, error) {\n\treq := LipSyncRequest{\n\t\tAudioURL:       audioURL,\n\t\tVideoURL:       videoURL,\n\t\tSynergizeAudio: true,\n\t}\n\n\thttpReq, err := BuildLipSyncRequest(cfg, req)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\thttpReq = httpReq.WithContext(ctx)\n\n\tresp, err := cfg.doHTTP(httpReq)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"lipsync API call: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\treturn \"\", fmt.Errorf(\"lipsync API error %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar result LipSyncResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {\n\t\treturn \"\", fmt.Errorf(\"decode lipsync response: %w\", err)\n\t}\n\treturn result.ID, nil\n}\n\n// CheckLipSyncStatus checks the status of a lip sync job.\nfunc CheckLipSyncStatus(ctx context.Context, cfg LipSyncConfig, jobID string) (*LipSyncResponse, error) {\n\thttpReq, err := BuildLipSyncStatusRequest(cfg, jobID)","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/video_gen/lipsync.go#L101-L137","documentation":"SubmitLipSync wraps errors from cfg.doHTTP(httpReq) — i.e. the request could not be completed at the transport level: DNS resolution failure, connection refused/TLS handshake error, timeout, or context cancellation. It is distinct from [453], which fires when the server responds with a non-2xx status; here there is no usable HTTP response at all.","triggerScenarios":"Calling SubmitLipSync when the lipsync provider host is unreachable (DNS failure, wrong host/port), the network is down, TLS certs are invalid/expired, cfg.doHTTP has no/rejecting timeout, or the caller's ctx is canceled before the response arrives.","commonSituations":"Provider outage or regional block; container without outbound internet/Egress rules blocking the API; proxy required but not configured; 5-second default timeout exceeded on slow uploads; test environment pointing at a non-existent host.","solutions":["Verify network connectivity/DNS to the lipsync base URL host (curl the base URL from the same machine)","Check ctx deadlines and cancelations — pass a context with an adequate timeout for media upload","Confirm TLS is valid (system CA bundle present in container images; correct scheme http vs https)","Inspect and unwrap the wrapped error with errors.Is(err, context.DeadlineExceeded)/net.Error to classify, then retry transient kinds with backoff"],"exampleFix":"// before\nid, err := SubmitLipSync(ctx, cfg, ...) // bare ctx may be canceled too early\n// after\nctx, cancel := context.WithTimeout(ctx, 60*time.Second)\ndefer cancel()\nid, err := SubmitLipSync(ctx, cfg, ...)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) { /* retry with backoff */ }\n}","handlingStrategy":"retry","validationCode":"// before calling: cheap reachability preflight\nctx, cancel := context.WithTimeout(ctx, 60*time.Second)\ndefer cancel()\nif err := ctx.Err(); err != nil {\n    return fmt.Errorf(\"context already done: %w\", err)\n}","typeGuard":"func isTransientNetErr(err error) bool {\n    var ne net.Error\n    if errors.As(err, &ne) && ne.Timeout() { return true }\n    return errors.Is(err, context.DeadlineExceeded) ||\n        errors.Is(err, syscall.ECONNREFUSED) ||\n        errors.Is(err, syscall.ECONNRESET)\n}","tryCatchPattern":"id, err := SubmitLipSync(ctx, cfg, ...)\nif err != nil {\n    if isTransientNetErr(err) {\n        // retry with exponential backoff, honoring ctx\n    }\n    if errors.Is(err, context.Canceled) {\n        // caller canceled; do not retry\n    }\n    return fmt.Errorf(\"submit failed: %w\", err)\n}","preventionTips":["Always pass a context with an explicit timeout sized for media uploads","Configure retries with exponential backoff for idempotent status checks; cap submit retries","Verify egress/firewall rules allow outbound HTTPS to the provider in each environment","Monitor DNS/connectivity to the provider endpoint in health checks"],"tags":["network","http-client","timeout","lipsync"],"backgroundTag":"network-request-failed","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"}