Billionmail/BillionMail · critical

failed to get option from database:

Error message

failed to get option from database: 

What it means

When the value is not in cache, GetOption queries the bm_options table (WHERE name = key). Any database error returned by the ORM is wrapped as "failed to get option from database: <driver error>". This signals an infrastructure/DB problem or a schema issue, not a missing option (that's the separate 'option not found' error).

Source

Thrown at core/internal/service/public/options_mgr.go:86

	// Try to get from cache
	cacheKey := o.buildCacheKey(key)
	cached, err := o.cache.Get(ctx, cacheKey)
	var jsonValue string

	if err != nil || cached == nil {
		// Cache miss, read from database
		var result struct {
			Value string `json:"value"`
		}

		err := g.DB().Model("bm_options").
			Where("name", key).
			Fields("value").
			Scan(&result)

		if err != nil {
			return errors.New("failed to get option from database: " + err.Error())
		}

		if result.Value == "" {
			return errors.New("option not found")
		}

		jsonValue = result.Value

		// Store in cache
		if err := o.cache.Set(ctx, cacheKey, jsonValue, o.expiration); err != nil {
			g.Log().Warning(ctx, "Failed to set option cache:", err)
		}
	} else {
		// Cache hit
		jsonValue = cached.String()
	}

	// Deserialize

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Read the wrapped driver message after the colon to identify the root cause (connection refused, relation does not exist, etc.).
  2. Verify PostgreSQL is running and reachable (docker compose ps, connection settings).
  3. Ensure schema migrations have created the bm_options table.
  4. Check Redis cache health — repeated DB fallbacks due to cache outages amplify DB load.
Defensive patterns

Strategy: retry

Validate before calling

// ping DB before batch option loads
if err := g.DB().PingContext(ctx); err != nil {
    return fmt.Errorf("database unavailable: %w", err)
}

Try / catch

if err := public.GetOption(ctx, key, &out); err != nil {
    if strings.Contains(err.Error(), "failed to get option from database") {
        // transient DB issue: retry with backoff
        return retry.Do(3, 500*time.Millisecond, func() error {
            return public.GetOption(ctx, key, &out)
        })
    }
    return err
}

Prevention

When it happens

Trigger: Database is down/unreachable, bm_options table missing (schema not migrated), or connection pool exhausted when GetOption falls through to the DB after a cache miss.

Common situations: Fresh deployment before migrations run; Postgres restarted or container not up; wrong DB credentials in config causing connection failures.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/acb4405933dc0aee. Report an issue: GitHub.