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 optionsView on GitHub (pinned to fc36c76c05)
Solutions
- Verify the exact key name exists: SELECT value FROM bm_options WHERE name = '<key>'.
- Call SetOption to create the option before reading it, or seed defaults during setup.
- Treat the error as 'use default': call sites should fall back to a sensible default value.
- 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
- Provide a typed wrapper that returns (value, found, err) semantics instead of string-matching.
- Seed all expected options with defaults during installation/migration.
- Centralize option key constants to avoid typos.
- On read, write back the default via SetOption so subsequent reads succeed.
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.