caddyserver/caddy · warning
STEK gob corrupted: %v
Error message
STEK gob corrupted: %v
What it means
The distributed STEK provider persists session ticket keys to storage as a gob; loadSTEK gob-decodes the stored bytes and wraps decode failures as 'STEK gob corrupted'. Notably, a storage read error (including not-exist) is NOT wrapped, so this specifically means bytes existed but did not decode — corruption or an incompatible gob schema.
Source
Thrown at modules/caddytls/distributedstek/distributedstek.go:128
}
// Next returns a channel which transmits the latest session ticket keys.
func (s *Provider) Next(doneChan <-chan struct{}) <-chan [][32]byte {
keysChan := make(chan [][32]byte)
go s.rotate(doneChan, keysChan)
return keysChan
}
func (s *Provider) loadSTEK() (distributedSTEK, error) {
var sg distributedSTEK
gobBytes, err := s.storage.Load(s.ctx, stekFileName)
if err != nil {
return sg, err // don't wrap, in case error is certmagic.ErrNotExist
}
dec := gob.NewDecoder(bytes.NewReader(gobBytes))
err = dec.Decode(&sg)
if err != nil {
return sg, fmt.Errorf("STEK gob corrupted: %v", err)
}
return sg, nil
}
func (s *Provider) storeSTEK(dstek distributedSTEK) error {
var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(dstek)
if err != nil {
return fmt.Errorf("encoding STEK gob: %v", err)
}
err = s.storage.Store(s.ctx, stekFileName, buf.Bytes())
if err != nil {
return fmt.Errorf("storing STEK gob: %v", err)
}
return nil
}
// getSTEK locks and loads the current STEK from storage. If noneView on GitHub (pinned to 50e54ee279)
Solutions
- Delete the stored STEK object so a fresh key set is generated (the provider creates and persists new STEKs when none exists); for file storage remove the stek file under the storage root, then reload
- If it recurs, check storage durability (disk health, fsync behavior, network storage consistency)
- After a Caddy upgrade causing schema mismatch, a one-time deletion is expected and safe — old ticket keys are ephemeral by design
Example fix
# before: recurring 'STEK gob corrupted' at startup ls /var/lib/caddy/storage/... # locate stek object # after: remove it and reload Caddy rm /var/lib/caddy/storage/<...>/stek # path per your storage config systemctl reload caddy
Defensive patterns
Strategy: fallback
Validate before calling
// Detect a corrupt STEK object before it breaks the provider
type distributedSTEK struct { Keys [][32]byte; NextRotation time.Time }
func stekLooksValid(b []byte) bool {
var s struct { Keys [][32]byte; NextRotation time.Time }
return gob.NewDecoder(bytes.NewReader(b)).Decode(&s) == nil && len(s.Keys) > 0
} Try / catch
// Since loadSTEK does not wrap storage.ErrNotExist, treat decode failure as stale: // delete the stored object so the provider mints fresh keys on next rotation. // (shell) rm "$CADDY_STORAGE_ROOT/.../stek" && systemctl reload caddy
Prevention
- Treat STEK objects as disposable cache — safe to delete after upgrades
- Use durable storage backends with atomic writes (certmagic file storage already rename-writes)
- Monitor for recurring corruption: it signals disk or storage-plugin faults
When it happens
Trigger: The stored stek file was truncated (e.g. crash during write), partially synced, or written by a different Caddy version whose distributedSTEK struct changed; manual tampering with the storage object.
Common situations: Crash or disk-full during a previous STEK write; upgrading Caddy across incompatible struct changes; copying storage buckets between environments mid-write.
Related errors
- Buggy browser is sending null Origin header.
- loading TLS storage module: %s
- creating TLS storage configuration: %v
- encoding STEK gob: %v
- storing STEK gob: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/dea909c58f248e19.
Report an issue: GitHub.