Billionmail/BillionMail · error
create status request: %w
Error message
create status request: %w
What it means
BuildLipSyncStatusRequest wraps errors from http.NewRequest when constructing the GET status URL "%s%s/%s" (base + lipSyncPath + jobID). As with [450], http.NewRequest fails only on bad method or unparsable URL, so a malformed base URL is the usual cause; an embedded path segment with invalid characters (often from jobID) also triggers it.
Source
Thrown at core/internal/service/video_gen/lipsync.go:96
}
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 {
return nil, fmt.Errorf("create status request: %w", err)
}
httpReq.Header.Set("x-api-key", cfg.APIKey)
return httpReq, nil
}
// SubmitLipSync submits a lip sync job and returns the job ID.
func SubmitLipSync(ctx context.Context, cfg LipSyncConfig, audioURL, videoURL string) (string, error) {
req := LipSyncRequest{
AudioURL: audioURL,
VideoURL: videoURL,
SynergizeAudio: true,
}
httpReq, err := BuildLipSyncRequest(cfg, req)
if err != nil {
return "", err
}View on GitHub (pinned to fc36c76c05)
Solutions
- Validate the base URL has scheme+host at config load time
- Sanitize the jobID: trim whitespace and ensure it matches the expected ID format before calling CheckLipSyncStatus
- url.PathEscape the jobID (or validate it as alphanumeric) before interpolation
- Unwrap the returned error to read url.Parse's specific message
Example fix
// before
resp, err := CheckLipSyncStatus(ctx, cfg, jobIDFromDB) // jobID may contain spaces
// after
jobID = strings.TrimSpace(jobIDFromDB)
if !validJobIDRe.MatchString(jobID) {
return fmt.Errorf("invalid lipsync jobID %q", jobID)
}
resp, err := CheckLipSyncStatus(ctx, cfg, jobID) Defensive patterns
Strategy: validation
Validate before calling
jobID = strings.TrimSpace(jobID)
if !regexp.MustCompile(`^[A-Za-z0-9_-]+$`).MatchString(jobID) {
return fmt.Errorf("invalid lipsync jobID %q", jobID)
} Type guard
func validJobID(id string) bool {
id = strings.TrimSpace(id)
return id != "" && !strings.ContainsAny(id, " /\\?#%{}")
} Try / catch
req, err := BuildLipSyncStatusRequest(cfg, jobID)
if err != nil {
return nil, fmt.Errorf("status check aborted for job %q: %w", jobID, err)
} Prevention
- Sanitize jobIDs when storing/retrieving them; never pass user-supplied strings raw into URLs
- Reuse the same base-URL validation as the submit path
- Test the empty-jobID path (the existing TestBuildLipSyncStatusRequest_EmptyJobID) in CI
When it happens
Trigger: Calling CheckLipSyncStatus with a LipSyncConfig whose base URL is empty/malformed, or a jobID containing characters that make url.Parse fail (spaces, control chars, raw non-ASCII) since jobID is interpolated into the URL path without escaping.
Common situations: Base URL env var misconfigured the same way as [450]; storing/logging a jobID that included whitespace or a full URL and passing it back unescaped; copy-pasted base URL with trailing newline.
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
- create lipsync request: %w
- lipsync API error %d: %s
- create download request: %w
- download lipsync video: %w
- download error %d
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/1d2c3b8cb66a6ab7.
Report an issue: GitHub.