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

  1. Check the wrapped %w error to identify the OS-level RNG failure (e.g. open /dev/urandom: no such file).
  2. Ensure /dev/urandom exists in the container/image (mount it if the base image omits it).
  3. Review seccomp/AppArmor filters and allow the getrandom(2) syscall.
  4. 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

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


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/bcc04e4ebe88e9b5. Report an issue: GitHub.