Billionmail/BillionMail · warning

option not found

Error message

option not found

What it means

After a cache miss, GetOption looks up the option row in bm_options. If the query succeeds but the value column is empty (row absent or stored value is empty string), it returns 'option not found'. This is the library's way of signaling that the requested option key has never been set.

Source

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

	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
	return o.deserialize(jsonValue, ptr)
}

// GetAllOptions Get all options

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify the exact key name exists: SELECT value FROM bm_options WHERE name = '<key>'.
  2. Call SetOption to create the option before reading it, or seed defaults during setup.
  3. Treat the error as 'use default': call sites should fall back to a sensible default value.
  4. Check for key-name typos or renames between code versions.

Example fix

// before
if err := public.GetOption(ctx, "warmup_enabled", &enabled); err != nil {
    return err
}
// after
if err := public.GetOption(ctx, "warmup_enabled", &enabled); err != nil {
    if err.Error() == "option not found" {
        enabled = true // default
        return nil
    }
    return err
}
Defensive patterns

Strategy: fallback

Validate before calling

// check existence first if you must
n, _ := g.DB().Model("bm_options").Where("name", key).Count()
exists := n > 0

Try / catch

if err := public.GetOption(ctx, key, &out); err != nil {
    if err.Error() == "option not found" {
        return defaultOut, nil
    }
    return err
}

Prevention

When it happens

Trigger: GetOption with a key that was never written via SetOption, or an option whose stored value was cleared to empty string.

Common situations: Reading optional settings on a fresh install before an admin saved them; typos in option key names; options removed by a cleanup/migration script.

Related errors


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