JuliusBrussee/caveman · error
cacheengine: driver needs non-empty provider and implementat
Error message
cacheengine: driver needs non-empty provider and implementation
What it means
Returned by cacheengine.NewEngine when the config.Drivers map contains an entry whose key trims/lower-cases to an empty provider string or whose Driver value is nil. Provider names are normalized (TrimSpace + ToLower) before this check, so a key of " " fails just like "". Each provider must map to a real Driver implementation before the Engine is constructed.
Source
Thrown at cacheengine/engine.go:88
maxShards = 64
}
maxRequestBytes := config.MaxRequestBytes
if maxRequestBytes == 0 {
maxRequestBytes = defaultInputByteLimit
}
maxStablePrefixBytes := config.MaxStablePrefixBytes
if maxStablePrefixBytes == 0 {
maxStablePrefixBytes = defaultInputByteLimit
}
resolver := config.ResolveProfile
if resolver == nil {
resolver = defaultProfile
}
drivers := make(map[string]Driver, len(config.Drivers))
for rawProvider, driver := range config.Drivers {
provider := strings.ToLower(strings.TrimSpace(rawProvider))
if provider == "" || driver == nil {
return nil, errors.New("cacheengine: driver needs non-empty provider and implementation")
}
if _, exists := drivers[provider]; exists {
return nil, fmt.Errorf("cacheengine: duplicate normalized driver provider %q", provider)
}
drivers[provider] = driver
}
return &Engine{
guard: cacheguard.New(), prefixSafety: newPrefixSafetyCache(8192),
maxKeyShards: maxShards, maxRequestBytes: maxRequestBytes, maxStablePrefixBytes: maxStablePrefixBytes,
resolveProfile: resolver, drivers: drivers,
}, nil
}
// Plan selects profitable stable-prefix cache boundaries without editing wire bytes.
func (e *Engine) Plan(request PlanRequest) (Plan, error) {
if e == nil || e.guard == nil || e.prefixSafety == nil {
return Plan{}, errors.New("cacheengine: nil engine")
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Ensure every Drivers map key is a non-blank provider name and every value is a non-nil Driver
- Check factory errors before inserting: if constructor returns nil driver with err, skip/abort instead of storing nil
- Filter empty keys when building the map from external configuration
- Watch for typed-nil interfaces: a (*myDriver)(nil) stored in a Driver interface is non-nil to ==nil only if the concrete type is nil pointer stored directly — store only successfully constructed values
Example fix
// before
if drv, err := newDriver(p); err != nil {
log.Println(err) // but still stores nil below in some path
}
drivers[p] = drv
// after
if drv, err := newDriver(p); err != nil {
return fmt.Errorf("provider %s: %w", p, err)
}
if strings.TrimSpace(p) == "" || drv == nil {
return errors.New("empty provider or nil driver")
}
drivers[p] = drv Defensive patterns
Strategy: validation
Validate before calling
func validDrivers(drivers map[string]cacheengine.Driver) error {
for name, d := range drivers {
if strings.TrimSpace(strings.ToLower(name)) == "" {
return fmt.Errorf("blank provider name %q", name)
}
if d == nil {
return fmt.Errorf("nil driver for provider %q", name)
}
}
return nil
} Type guard
func hasDrivers(cfg cacheengine.Config) bool {
for name, d := range cfg.Drivers {
if strings.TrimSpace(name) != "" && d != nil {
return true
}
}
return false
} Try / catch
engine, err := cacheengine.NewEngine(cfg)
if err != nil {
if strings.Contains(err.Error(), "driver needs non-empty provider") {
return fmt.Errorf("driver registry misconfigured: %+v", cfg.Drivers)
}
return err
} Prevention
- Never store a driver when its constructor returned an error; fail the registration loop
- Beware typed-nil interfaces: only insert values from successful constructor calls
When it happens
Trigger: Building Config{Drivers: map[string]Driver{"": drv}} or including a nil Driver value (e.g. a typed-nil from a constructor that returned nil on its own error). Constructing the map from external config where a blank provider key sneaks in.
Common situations: Registering drivers in a loop where a factory returns nil for unsupported providers and the nil is stored anyway; config-driven provider lists with an empty entry; trimmed whitespace keys like " OpenAI " are fine (they normalize) but fully-blank keys are not.
Related errors
- cacheengine: nil engine
- cachebench: nil cache engine
- cachebench: no providers
- cachebench: provider population exceeds 1024
- cachebench: invalid observation read limits
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/7bb9c73b98921ff5.
Report an issue: GitHub.