nektos/act · critical

generate auth token: %w

Error message

generate auth token: %w

What it means

The artifact cache server generates a random 16-byte auth token (crypto/rand) that scopes every HTTP route ('/<token>/api/...'). If rand.Read fails — which for crypto/rand realistically means the OS entropy source is unavailable or blocked — server startup aborts with the wrapped 'generate auth token: %w' error before the HTTP router is created.

Source

Thrown at pkg/artifactcache/handler.go:92

		return nil, err
	}
	h.storage = storage

	if customExternalURL != "" {
		h.customExternalURL = customExternalURL
	}

	if outboundIP != "" {
		h.outboundIP = outboundIP
	} else if ip := common.GetOutboundIP(); ip == nil {
		return nil, fmt.Errorf("unable to determine outbound IP address")
	} else {
		h.outboundIP = ip.String()
	}

	tokenBytes := make([]byte, 16)
	if _, err := rand.Read(tokenBytes); err != nil {
		return nil, fmt.Errorf("generate auth token: %w", err)
	}
	h.token = hex.EncodeToString(tokenBytes)

	router := httprouter.New()
	base := "/" + h.token + apiPath
	router.GET(base+"/cache", h.middleware(h.find))
	router.POST(base+"/caches", h.middleware(h.reserve))
	router.PATCH(base+"/caches/:id", h.middleware(h.upload))
	router.POST(base+"/caches/:id", h.middleware(h.commit))
	router.GET(base+"/artifacts/:id", h.middleware(h.get))
	router.POST(base+"/clean", h.middleware(h.clean))

	h.router = router

	h.gcCache()

	listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", h.outboundIP, port))
	if err != nil {

View on GitHub (pinned to 4f41128141)

Solutions

  1. Verify the OS entropy source: check that /dev/urandom is readable and getrandom is not blocked by seccomp/apparmor profiles.
  2. If running act in a container, allow getrandom(2) in the security profile or use a less restrictive runtime.
  3. On entropy-starved VMs, wait until the pool is ready or install haveged/virtio-rng.
  4. Update the Go toolchain / act build if the failure persists, since older runtimes had entropy bugs on some platforms.

Example fix

# before
act -j build   # inside container with seccomp blocking getrandom
# -> generate auth token: ...

# after
# run with a profile permitting getrandom, e.g.:
docker run --security-opt seccomp=unconfined ... act -j build
Defensive patterns

Strategy: retry

Validate before calling

package main

import (
	"crypto/rand"
	"fmt"
	"os"
)

func entropyAvailable() error {
	f, err := os.Open("/dev/urandom")
	if err != nil {
		return fmt.Errorf("entropy source unavailable: %w", err)
	}
	defer f.Close()
	buf := make([]byte, 8)
	if _, err := rand.Read(buf); err != nil {
		return fmt.Errorf("crypto/rand read failed: %w", err)
	}
	return nil
}

Try / catch

handler, err := artifactcache.NewHandler(...)
if err != nil && strings.Contains(err.Error(), "generate auth token") {
    // entropy starvation can be transient on cold VMs: brief retry before failing
    time.Sleep(2 * time.Second)
    handler, err = artifactcache.NewHandler(...)
    if err != nil {
        return fmt.Errorf("system entropy unavailable (getrandom blocked?); fix sandbox/kernel: %w", err)
    }
}

Prevention

When it happens

Trigger: Starting act (or NewHandler directly) on a system where crypto/rand cannot read entropy: early-boot entropy starvation on minimal VMs/containers, a broken /dev/urandom, or seccomp/container runtimes blocking getrandom(2).

Common situations: act inside tightly sandboxed containers with syscalls filtered; embedded/minimal systems before the entropy pool is initialized; rare kernel/runtime misconfigurations; Go runtimes on platforms with faulty entropy plumbing.

Related errors


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/6796b3fe5058e765. Report an issue: GitHub.