Billionmail/BillionMail · error
check lip sync status: %w
Error message
check lip sync status: %w
What it means
Each poll iteration calls CheckLipSyncStatus; if that HTTP/API call fails, pollLipSync wraps the failure with 'check lip sync status: %w' and aborts immediately rather than retrying. The wrapped cause is the actual network/API error.
Source
Thrown at core/internal/service/video_gen/orchestrator.go:409
if defaultID != "" {
return defaultID, nil
}
return "", fmt.Errorf("no voice configured: set VOICE_SAMPLE_URL or VOICE_DEFAULT_ID")
}
// pollLipSync polls lip sync status until completed or timeout.
func pollLipSync(ctx context.Context, cfg LipSyncConfig, jobID string) (string, error) {
deadline := time.Now().Add(lipSyncTimeout)
for {
if time.Now().After(deadline) {
return "", fmt.Errorf("lip sync timed out after %v", lipSyncTimeout)
}
resp, err := CheckLipSyncStatus(ctx, cfg, jobID)
if err != nil {
return "", fmt.Errorf("check lip sync status: %w", err)
}
switch resp.Status {
case "completed":
if resp.VideoURL == "" {
return "", fmt.Errorf("lip sync completed but no video URL")
}
return resp.VideoURL, nil
case "failed":
return "", fmt.Errorf("lip sync failed: %s", resp.Error)
}
time.Sleep(lipSyncPollDelay)
}
}
// withRetry retries a function up to maxRetries times with exponential backoff.
func withRetry[T any](fn func() (T, error)) (T, error) {View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped cause (%w) to identify the underlying provider error
- Verify the lip-sync API key and endpoint configuration
- Retry the pipeline; add retry/backoff around status checks for transient errors
- Check ctx cancellation: if the parent request timed out, extend the caller's deadline
Example fix
// before
resp, err := CheckLipSyncStatus(ctx, cfg, jobID)
if err != nil {
return "", fmt.Errorf("check lip sync status: %w", err)
}
// after
resp, err := CheckLipSyncStatus(ctx, cfg, jobID)
if err != nil {
if errors.Is(err, context.Canceled) { return "", err }
// transient: keep polling instead of failing
time.Sleep(lipSyncPollDelay)
continue
} Defensive patterns
Strategy: try-catch
Validate before calling
if cfg.APIKey == "" {
return fmt.Errorf("lip sync API key not configured")
}
if err := ctx.Err(); err != nil {
return err
} Type guard
func isTransientLipSyncErr(err error) bool {
return err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded)
} Try / catch
url, err := pollLipSync(ctx, cfg, jobID)
var apiErr *APIStatusError
if errors.As(err, &apiErr) && apiErr.Code >= 500 {
// transient upstream error — safe to retry the whole stage
} Prevention
- Rotate and verify the provider API key in all environments
- Add retry/backoff around status checks for 5xx and network errors
- Check ctx deadlines: pass a context with enough budget for the full poll loop
- Monitor the provider status page and set alerts
When it happens
Trigger: Any failure of CheckLipSyncStatus during polling: HTTP 4xx/5xx from the provider, invalid API key, DNS/network failure, context cancellation, or malformed provider response.
Common situations: Expired or missing provider API key; provider 500s mid-job; network blips in the container; ctx cancelled because the parent RunPipeline request timed out.
Related errors
- claude script generation: %w
- base URL not configured
- failed to list containers: %w
- IPv4 network format is incorrect, please use CIDR format (e.
- %s
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/3c59b68450c19cb9.
Report an issue: GitHub.