Billionmail/BillionMail · error
contact %d missing website_url
Error message
contact %d missing website_url
What it means
RunPipeline validates that the contact's attribs map contains a non-empty website_url before proceeding with screenshot capture. The video generation pipeline (screenshots, script, landing page) is built around the contact's website, so without website_url the job cannot proceed. The error is raised after loadContactAttribs succeeded, meaning the contact row exists and has attribs, but the attribs JSON lacks the website_url key or has it set to an empty string.
Source
Thrown at core/internal/service/video_gen/orchestrator.go:161
g.Log().Infof(ctx, "video job %d starting pipeline for contact %d <%s>", job.ID, job.ContactID, job.ContactEmail)
tmpDir := fmt.Sprintf("/tmp/video_gen_%d", job.ID)
if err := os.MkdirAll(tmpDir, 0755); err != nil {
markFailed(ctx, job.ID, "setup", err)
return err
}
// 1. Load contact attribs
attribs, err := loadContactAttribs(ctx, job.ContactID, job.GroupID)
if err != nil {
markFailed(ctx, job.ID, "load_contact", err)
return err
}
websiteURL := attribs["website_url"]
businessName := attribs["business_name"]
ownerName := attribs["owner_name"]
if websiteURL == "" {
err = fmt.Errorf("contact %d missing website_url", job.ContactID)
markFailed(ctx, job.ID, "load_contact", err)
return err
}
// Parse signals
signals := parseSignals(attribs["lead_signals"])
// 2. Screenshots + Annotate
updateJobStatus(ctx, job.ID, JobProcessing, "screenshot", "")
screenshots, err := withRetry(func() (*ScreenshotResult, error) {
return CaptureScreenshots(ctx, DefaultScreenshotConfig(websiteURL, businessName, tmpDir))
})
if err != nil {
markFailed(ctx, job.ID, "screenshot", err)
return err
}
updateJobStatus(ctx, job.ID, JobProcessing, "annotate", "")View on GitHub (pinned to fc36c76c05)
Solutions
- Check the contact row in bm_contacts (SELECT attribs FROM bm_contacts WHERE id=<contactID> AND group_id=<groupID>) and confirm website_url exists and is non-empty
- Fix the import/enrichment process so website_url is always populated before enqueuing video jobs
- Add a pre-enqueue guard in EnqueueVideoJob or the caller that validates attribs["website_url"] != "" and skips/fails the contact early instead of consuming a pipeline slot
- If the website is genuinely unknown, exclude such contacts from video generation campaigns
Example fix
// before
result, err := EnqueueVideoJob(ctx, contact.ID, contact.Email, groupID)
// after
attribs, _ := loadContactAttribs(ctx, contact.ID, groupID)
if attribs["website_url"] == "" {
return fmt.Errorf("skip contact %d: no website_url", contact.ID)
}
result, err := EnqueueVideoJob(ctx, contact.ID, contact.Email, groupID) Defensive patterns
Strategy: validation
Validate before calling
attribs, err := loadContactAttribs(ctx, contactID, groupID)
if err != nil { return err }
if strings.TrimSpace(attribs["website_url"]) == "" {
return fmt.Errorf("contact %d has no website_url; not eligible for video generation", contactID)
} Try / catch
if err := RunPipeline(ctx, job); err != nil {
var missing *MissingFieldError
if errors.As(err, &missing) && missing.Field == "website_url" {
// skip this contact permanently, don't retry
skipContact(job.ContactID, "no website_url")
}
} Prevention
- Make website_url a required column/field at contact import time with validation on write
- Validate attribs in EnqueueVideoJob before inserting a pending job
- Monitor the bm_video_jobs error column for 'missing website_url' to catch import gaps early
- Give the campaign UI a filter to exclude contacts without a website
When it happens
Trigger: RunPipeline calls loadContactAttribs(contactID, groupID), gets a valid map, but attribs["website_url"] is empty — i.e. the bm_contacts.attribs JSON either omits the website_url field or stores "".
Common situations: Contacts imported via CSV/Excel without the website_url column mapped; contacts created manually by users who skipped the website field; upstream enrichment jobs that failed silently and wrote attribs without website_url; leads sourced from channels (e.g. Google Maps scraping) where the website was not present on the source record.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- no scenes provided
- required column 'email' not found
- You cannot create more than 5000 batches
- No log files found in the given date range
- invalid start_date: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/b5c28db335c2d752.
Report an issue: GitHub.