Billionmail/BillionMail · error
create download request: %w
Error message
create download request: %w
What it means
DownloadLipSyncVideo builds the GET request to the completed video's CDN URL with http.NewRequestWithContext. This error wraps request-construction failure, which in practice happens only when videoURL fails Go's URL parsing — empty string, containing spaces/control characters, or otherwise malformed. It is raised locally before any network call.
Source
Thrown at core/internal/service/video_gen/lipsync.go:169
return nil, fmt.Errorf("lipsync status API error %d: %s", resp.StatusCode, string(body))
}
var result LipSyncResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("decode lipsync status: %w", err)
}
return &result, nil
}
// DownloadLipSyncVideo downloads the completed lip sync video to the output directory.
func DownloadLipSyncVideo(ctx context.Context, cfg LipSyncConfig, videoURL, filename string) (string, error) {
if err := os.MkdirAll(cfg.OutputDir, 0755); err != nil {
return "", fmt.Errorf("create output dir: %w", err)
}
req, err := http.NewRequestWithContext(ctx, "GET", videoURL, nil)
if err != nil {
return "", fmt.Errorf("create download request: %w", err)
}
resp, err := cfg.doHTTP(req)
if err != nil {
return "", fmt.Errorf("download lipsync video: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("download error %d", resp.StatusCode)
}
outPath := filepath.Join(cfg.OutputDir, filename)
f, err := os.Create(outPath)
if err != nil {
return "", fmt.Errorf("create output file: %w", err)
}
defer f.Close()View on GitHub (pinned to fc36c76c05)
Solutions
- Guard the caller: only download when status == "completed" AND result.VideoURL is a non-empty http(s) URL.
- Sanitize the URL (strings.TrimSpace, url.Parse validation) before calling DownloadLipSyncVideo.
- If the URL is persisted, re-fetch the job status to get a fresh signed CDN URL — signed URLs can expire and be replaced.
- Log the offending videoURL in the caller so the malformed value is identifiable.
Example fix
// before: downloads regardless of validation
path, err := video_gen.DownloadLipSyncVideo(ctx, cfg, resp.VideoURL, name)
// after: validate before downloading
u, err := url.Parse(strings.TrimSpace(resp.VideoURL))
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("invalid video URL %q", resp.VideoURL)
}
path, err := video_gen.DownloadLipSyncVideo(ctx, cfg, u.String(), name) Defensive patterns
Strategy: validation
Validate before calling
func validVideoURL(raw string) bool {
u, err := url.Parse(strings.TrimSpace(raw))
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}
// call site:
if resp.Status != "completed" || !validVideoURL(resp.VideoURL) {
return fmt.Errorf("lipsync job not downloadable (status=%q url=%q)", resp.Status, resp.VideoURL)
} Type guard
func downloadableLipSyncResult(r *video_gen.LipSyncResponse) bool {
return r != nil && r.Status == "completed" && validVideoURL(r.VideoURL)
} Try / catch
path, err := video_gen.DownloadLipSyncVideo(ctx, cfg, videoURL, filename)
if err != nil {
if strings.Contains(err.Error(), "create download request") {
return fmt.Errorf("malformed video URL %q: %w", videoURL, err)
}
return err
} Prevention
- Check Status == "completed" and VideoURL non-empty before downloading.
- Trim whitespace from URLs coming from the API or database.
- Re-fetch status if a persisted signed CDN URL may have expired.
- Use url.Parse as a cheap pre-check in any code path that consumes VideoURL.
When it happens
Trigger: Calling DownloadLipSyncVideo with an empty videoURL (e.g. caller ignored the job Status and passed the zero-value VideoURL field from LipSyncResponse), a URL with raw spaces or unescaped characters, or a video_url field from the API that is a relative path or malformed.
Common situations: Treating status=="completed" as sufficient without checking VideoURL != ""; storing the URL in a database and losing scheme/host; Sync Labs returning an error message in video_url on partially failed jobs; copy-pasted URLs with trailing whitespace.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- invalid base URL format: %w
- base URL must use http or https protocol
- create lipsync request: %w
- create status request: %w
- required column 'email' not found
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/50e07f0eb1ef79ad.
Report an issue: GitHub.