caddyserver/caddy · warning
cannot reuse socket %v: unix socket is already in use by ano
Error message
cannot reuse socket %v: unix socket is already in use by another process
What it means
During ECH key rotation, a config older than rotationInterval (30 days) with no Replaced timestamp needed a replacement, and generateAndStoreECHConfig failed — it could not generate an ECH keypair/config for the public name or persist it to storage.
Source
Thrown at listen_reuseUnixSocket_windows.go:62
// Abstract Unix sockets do not require us to remove stale socket files.
return nil, nil
}
// On Windows, we're using the `fakeCloseListener` wrappers around a single, ever-living listener.
// So, if there's an active listener entry in the pool, we're the current owner of the Unix socket file.
_, socketBelongsToCurrentProcess := listenerPool.References(listenerKey(network, addr))
if socketBelongsToCurrentProcess {
// Reuse/cleanup is entirely handled by the refcounting mechanism in `listenerPool`.
return nil, nil
}
// If the socket file does not exist or has no backing server process, this will fail instantly.
connection, err := net.DialTimeout("unix", addr, 10*time.Millisecond)
if err == nil {
connection.Close()
return nil, fmt.Errorf("cannot reuse socket %v: %w", addr, errUnixSocketAlreadyInUse)
}
// Windows returns this error code both if the socket file does not exist and if it isn't backed by a server process anymore.
// See: https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2#wsaeconnrefused
const WSAECONNREFUSED syscall.Errno = 10061
var errno syscall.Errno
hasNoListeningServerProcess := errors.As(err, &errno) && errno == WSAECONNREFUSED
if !hasNoListeningServerProcess {
return nil, fmt.Errorf("cannot reuse socket %v: %w", addr, errUnixSocketAlreadyInUse)
}
// If the socket file exists, it hasn't been created by our process, and it seemingly
// isn't backed by a server process anymore. Try to delete it so we can bind to it later.
err = os.Remove(addr)
if err == nil {View on GitHub (pinned to 50e54ee279)
Solutions
- Check the wrapped error from generateAndStoreECHConfig for the exact failing step.
- Ensure writable storage and adequate disk space on all instances.
- Fix backend connectivity; rotation retries on the next maintenance tick.
- If config ID collisions are indicated in a cluster, ensure all instances share one storage backend so ID allocation is serialized by the ech_rotation lock.
Defensive patterns
Strategy: retry
Try / catch
Retry on next rotation tick after fixing storage; if generation itself fails (rare), capture the inner error and report upstream.
Prevention
- Keep data volumes writable and non-full for the 30-day rotation window.
- Use one shared storage per cluster to prevent config ID allocation races.
- Monitor for rotation failures so old keys do not linger past intended lifetimes.
When it happens
Trigger: generateAndStoreECHConfig: HPKE key generation failure (extremely rare), finding a free config ID via storage trial paths failing, or storage.Store of key.bin/config.bin/meta.json under ech/configs/<id> failing (read-only, full disk, backend outage).
Common situations: Data volume full or read-only after 30 days of uptime when rotation first triggers; storage credentials expiring; a cluster peer holding conflicting config IDs due to divergent storage views.
Related errors
- --output is required
- syntax error: unexpected token '%s', expecting '%s', at %s:%
- --input is required
- missing 'req' argument
- protocol argument was not a string
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/69ff4119c39a6a8e.
Report an issue: GitHub.