Billionmail/BillionMail · error

value cannot be nil

Error message

value cannot be nil

What it means

OptionsMgr.SetOption in core/internal/service/public/options_mgr.go rejects a nil value with "value cannot be nil" before serializing, because it JSON-serializes the value and a nil interface{} cannot be meaningfully stored. This fail-fast guard prevents writing unusable option records.

Source

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

// NewOptionsMgr Create options manager
func NewOptionsMgr() *OptionsMgr {
	return &OptionsMgr{
		cache:      gcache.New(),
		expiration: time.Hour * 24, // Default 24 hours cache
	}
}

// OptionsMgrInstance Options manager singleton
var OptionsMgrInstance = NewOptionsMgr()

// SetOption Set option
func (o *OptionsMgr) SetOption(ctx context.Context, key string, value interface{}) error {
	if key == "" {
		return errors.New("key cannot be empty")
	}

	if value == nil {
		return errors.New("value cannot be nil")
	}

	// Serialize value
	jsonValue, err := o.serialize(value)
	if err != nil {
		return err
	}

	// Save to database
	if err := o.saveToDatabase(ctx, key, jsonValue); err != nil {
		return err
	}

	// Update cache
	cacheKey := o.buildCacheKey(key)
	if err := o.cache.Set(ctx, cacheKey, jsonValue, o.expiration); err != nil {
		return err
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Provide a concrete value or a typed zero value (e.g. "", 0, false) instead of nil.
  2. Check where the value comes from — handle missing map entries and unset request fields explicitly before calling.
  3. If deleting an option is intended, use the manager's delete/removal method instead of setting nil.

Example fix

// before
var val interface{} // nil
OptionsMgrInstance.SetOption(ctx, "site_name", val) // value cannot be nil
// after
val := req.SiteName
if val == nil {
    val = "" // store explicit empty value or skip the update
}
return OptionsMgrInstance.SetOption(ctx, "site_name", val)
Defensive patterns

Strategy: validation

Validate before calling

if value == nil {
    return errors.New("option value is required; use a typed zero value or delete the option instead")
}
err := OptionsMgrInstance.SetOption(ctx, key, value)

Type guard

func hasValue(v interface{}) bool { return v != nil }

Try / catch

if err := OptionsMgrInstance.SetOption(ctx, key, value); err != nil {
    if err.Error() == "value cannot be nil" {
        return fmt.Errorf("option %q has no value; pass a concrete value or remove the option", key)
    }
    return err
}

Prevention

When it happens

Trigger: Calling OptionsMgrInstance.SetOption(ctx, key, nil) — commonly passing a nil interface from an uninitialized pointer, a map lookup that returned the zero value with ok=false ignored, or an optional request field that was never set.

Common situations: Settings handlers binding request JSON where the value field is absent, refactors where the value variable lost its default, or code passing the result of a failed type assertion (var v T; v == nil).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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