caddyserver/caddy · error · APIError
Buggy browser is sending null Origin header.
Error message
Buggy browser is sending null Origin header.
What it means
loadSTEK() returned an error other than fs.ErrNotExist while reading the persisted STEK from storage. The provider distinguishes 'no keys yet' (fine, will create) from any other read failure (a real problem), and this error is the latter.
Source
Thrown at admin.go:849
return
}
if strings.Contains(r.Header.Get("Sec-Fetch-Mode"), "no-cors") {
// turns out web pages can just disable the same-origin policy (!???!?)
// but at least browsers let us know that's the case, holy heck
h.handleError(w, r, APIError{
HTTPStatus: http.StatusBadRequest,
Err: errors.New("client attempted to make request by disabling same-origin policy using no-cors mode"),
Message: "Disabling same-origin restrictions is not allowed.",
})
return
}
if r.Header.Get("Origin") == "null" {
// bug in Firefox in certain cross-origin situations (yikes?)
// (not strictly a security vuln on its own, but it's red flaggy,
// since it seems to manifest in cross-origin contexts)
h.handleError(w, r, APIError{
HTTPStatus: http.StatusBadRequest,
Err: errors.New("invalid origin 'null'"),
Message: "Buggy browser is sending null Origin header.",
})
return
}
if h.enforceHost {
// DNS rebinding mitigation
err := h.checkHost(r)
if err != nil {
h.handleError(w, r, err)
return
}
}
_, hasOriginHeader := r.Header["Origin"]
_, hasSecHeader := r.Header["Sec-Fetch-Mode"]
if h.enforceOrigin || hasOriginHeader || hasSecHeader {
// cross-site mitigationView on GitHub (pinned to 50e54ee279)
Solutions
- Inspect the wrapped error to see if it is a connectivity/permission failure (fix storage) versus a decode failure (corrupt data).
- For corrupt local data, stop Caddy and delete the STEK key from the data directory (it lives under the storage root; deleting it forces clean regeneration — only session resumption is lost).
- For remote storage, restore backend health and restart Caddy.
- Verify all cluster instances run compatible Caddy versions so the gob encoding of distributedSTEK matches.
Example fix
// before: corrupt stek key file in storage ls /var/lib/caddy/locks # locate storage keys # after: stop caddy, remove the stek entry, restart to regenerate systemctl stop caddy rm -rf /var/lib/caddy/stek* # path depends on storage layout systemctl start caddy
Defensive patterns
Strategy: retry
Type guard
// Distinguish 'no keys yet' (benign) from real load failures when implementing custom storage:
_, err := storage.Load(ctx, stekKeyName)
if errors.Is(err, fs.ErrNotExist) { /* first run: ok */ } else if err != nil { /* real failure */ } Try / catch
On this error, inspect errors.Is/As on the chain: fs.ErrNotExist is handled internally, so any surfaced error is a genuine storage fault — remediate storage, then restart to retry the load.
Prevention
- Use storage backends with atomic writes to avoid truncated STEK data.
- Keep cluster members on the same Caddy version so gob schemas match.
- Back up the data directory before upgrades.
- Do not hand-edit files under Caddy's storage.
When it happens
Trigger: storage.Load on the STEK key returns a non-ErrNotExist error: storage backend unreachable, permission denied on the key file, or gob decoding of a corrupt/truncated persisted STEK fails.
Common situations: Corrupted storage after a crash mid-write; partially synced distributed storage (S3 eventual consistency anomalies); permission changes on the data directory; Redis flushing/failing between the lock and the load.
Related errors
- WebSocket connections aren't allowed.
- Disabling same-origin restrictions is not allowed.
- syntax error: unexpected token '%s', expecting '%s', at %s:%
- ErrInvalidSplitPath
- private key does not match issuer public key
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/8f0af6d583885b42.
Report an issue: GitHub.