Billionmail/BillionMail · error
enqueue video job: %w
Error message
enqueue video job: %w
What it means
EnqueueVideoJob inserts a pending row into the bm_video_jobs table via GoFrame's g.DB(). When the INSERT fails (connection error, missing table, constraint violation), the raw DB error is wrapped with 'enqueue video job: %w'. Note ensureTable only logs failures with g.Log().Warning — if table creation silently failed, the very next Insert fails here with 'relation "bm_video_jobs" does not exist'.
Source
Thrown at core/internal/service/video_gen/orchestrator.go:87
`)
if err != nil {
g.Log().Warning(ctx, "create bm_video_jobs table: ", err)
}
})
}
// EnqueueVideoJob inserts a pending job into bm_video_jobs.
func EnqueueVideoJob(ctx context.Context, contactID int, email string, groupID int) (int, error) {
ensureTable(ctx)
result, err := g.DB().Model("bm_video_jobs").Ctx(ctx).Insert(g.Map{
"contact_id": contactID,
"contact_email": email,
"group_id": groupID,
"status": JobPending,
})
if err != nil {
return 0, fmt.Errorf("enqueue video job: %w", err)
}
id, _ := result.LastInsertId()
return int(id), nil
}
// ProcessVideoJobs polls for pending jobs and launches pipelines.
// Called by gtimer every 30s.
func ProcessVideoJobs(ctx context.Context) {
ensureTable(ctx)
var jobs []VideoJob
err := g.DB().Model("bm_video_jobs").Ctx(ctx).
Where("status", JobPending).
OrderAsc("id").
Limit(maxConcurrentJobs).
Scan(&jobs)
if err != nil {
g.Log().Warning(ctx, "query pending video jobs: ", err)View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped (%w) DB error — 'relation does not exist' means run the CREATE TABLE manually or fix the ensureTable failure path.
- Check DB connectivity and the GoFrame DB config (host, port, user, password, database) with a direct psql connection.
- Grant the app DB user CREATE/INSERT privileges on the schema, or pre-create bm_video_jobs in your migration set instead of relying on ensureTable.
- Make ensureTable fail loudly (return an error) instead of only logging a warning, so this failure surfaces at startup.
- Verify search_path/schema matches between the migration and the runtime connection.
Example fix
// before
func ensureTable(ctx context.Context) {
tableOnce.Do(func() {
_, err := g.DB().Exec(ctx, `CREATE TABLE IF NOT EXISTS bm_video_jobs (...)`)
if err != nil {
g.Log().Warning(ctx, "create bm_video_jobs table: ", err)
}
})
}
// after
// pre-create the table in a migration; at runtime fail fast on DB errors:
result, err := g.DB().Model("bm_video_jobs").Ctx(ctx).Insert(g.Map{...})
if err != nil {
return 0, fmt.Errorf("enqueue video job: %w", err) // now wrapped error points at real DB cause
} Defensive patterns
Strategy: try-catch
Validate before calling
// before enqueueing: verify table exists and DB is reachable
ctxT, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if _, err := g.DB().Exec(ctxT, "SELECT 1 FROM bm_video_jobs LIMIT 1"); err != nil {
// table missing or DB down — surface immediately instead of failing at Insert
return fmt.Errorf("bm_video_jobs not ready: %w", err)
} Type guard
func isMissingTable(err error) bool {
return err != nil && strings.Contains(strings.ToLower(err.Error()), "does not exist")
}
func isConnectionError(err error) bool {
return errors.Is(err, context.DeadlineExceeded) || strings.Contains(strings.ToLower(err.Error()), "connection refused")
} Try / catch
jobID, err := EnqueueVideoJob(ctx, contactID, email, groupID)
if err != nil {
switch {
case isMissingTable(err):
// run migration / create table explicitly, then retry once
case isConnectionError(err):
// check DB config/health, retry after backoff
}
return fmt.Errorf("enqueue video job: %w", err)
} Prevention
- Pre-create bm_video_jobs in a proper migration rather than relying on ensureTable's best-effort sync.Once
- Change ensureTable to return/propagate errors instead of only logging a Warning
- Check LastInsertId error too — with Postgres it's often unsupported; prefer RETURNING id
- Validate DB config and connectivity as a startup health check before accepting jobs
- Grant the app role INSERT (and CREATE if ensureTable stays) on the target schema
When it happens
Trigger: g.DB().Model("bm_video_jobs").Insert(...) errors: DB unreachable/wrong credentials, bm_video_jobs missing because ensureTable's CREATE TABLE failed earlier, schema drift (a required column absent after a migration), or a Postgres error such as invalid input for contact_email/group_id.
Common situations: Fresh deployment where the DB user lacks CREATE privilege so ensureTable's warning was missed; Postgres down or misconfigured DSN in config; manual schema changes dropping the table; migration created the table in a different schema/search_path; connection pool exhausted under bulk enqueues from GenerateVideo.
Related errors
- failed to insert alias: %v
- load contact attribs: %w
- Failed to get the total number of exception recipients: %w
- Failed to get the exception recipient list: %w
- Failed to add exception recipient: %w
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/8b9f55dc6566dc38.
Report an issue: GitHub.