cloudflare/cloudflared · error
failed to generate lock ID: %w
Error message
failed to generate lock ID: %w
What it means
newLockID wraps crypto/rand.Read failure while generating the 16-byte random identifier written into the lock file. The lock ID uniquely identifies the lock holder; without it the library cannot safely create the lock content, so it aborts. crypto/rand.Read effectively only fails when the OS entropy source is unavailable.
Source
Thrown at token/token.go:268
p, err := process.NewProcess(pid)
if err != nil {
return lockContent{}, fmt.Errorf("failed to look up own process: %w", err)
}
ct, err := p.CreateTime()
if err != nil {
return lockContent{}, fmt.Errorf("failed to get own start time: %w", err)
}
id, err := newLockID()
if err != nil {
return lockContent{}, err
}
return lockContent{PID: pid, StartTime: ct, ID: id}, nil
}
func newLockID() (string, error) {
var b [16]byte
if _, err := rand.Read(b[:]); err != nil {
return "", fmt.Errorf("failed to generate lock ID: %w", err)
}
return hex.EncodeToString(b[:]), nil
}
// isLockFileStale reads the lock file and checks whether the owning process
// is dead or has a mismatched start time. Returns (true, content, nil) if
// stale, (false, content, nil) if actively held, or an error if the file
// cannot be read.
func isLockFileStale(path string) (bool, lockContent, error) {
data, err := os.ReadFile(path) // nolint: gosec
if err != nil {
return false, lockContent{}, err
}
var content lockContent
if err := json.Unmarshal(data, &content); err != nil {
// corrupt or empty file (treat as stale)
return true, lockContent{}, nil
}View on GitHub (pinned to 2253eeeb25)
Solutions
- Check the wrapped %w error to identify the OS-level RNG failure (e.g. open /dev/urandom: no such file).
- Ensure /dev/urandom exists in the container/image (mount it if the base image omits it).
- Review seccomp/AppArmor filters and allow the getrandom(2) syscall.
- Update Go toolchain — modern Go uses getrandom(2) and virtually never fails after kernel 3.17 boot.
Example fix
// before go test ./token/... // fails in sandbox with 'failed to generate lock ID' // after: docker run with default (unfiltered) seccomp and /dev/urandom docker run --security-opt seccomp=default.json --tmpfs /dev:rw ...
Defensive patterns
Strategy: retry
Validate before calling
var probe [16]byte
if _, err := rand.Read(probe[:]); err != nil {
// OS entropy source unavailable; lock ID generation will fail
} Try / catch
content, err := createLockFile(path)
if err != nil {
if strings.Contains(err.Error(), "failed to generate lock ID") {
// transient OS RNG failure: retry once after short delay
time.Sleep(50 * time.Millisecond)
return createLockFile(path)
}
return err
} Prevention
- Do not filter the getrandom(2) syscall in sandboxes/seccomp profiles.
- Ensure /dev/urandom exists in minimal container images.
- Use a recent Go toolchain where crypto/rand virtually never fails.
- Retry once on failure before surfacing the error to the user.
When it happens
Trigger: Called from newSelfLockContent during createLockFile when the operating system's cryptographic RNG fails — e.g. /dev/urandom unusable or getrandom(2) syscall blocked by seccomp in a sandboxed container.
Common situations: Highly restricted sandboxes (gVisor, Firecracker minimal images, embedded Linux) where /dev/urandom is missing or the getrandom syscall is filtered; extremely early boot before entropy init on old kernels.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- couldn't generate the secret for your new tunnel
- failed to get own start time: %w
- ErrUnauthorized
- ErrBadRequest
- Decoded tunnel secret must be at least 32 bytes long
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/bcc04e4ebe88e9b5.
Report an issue: GitHub.