gastownhall/beads · critical

httpapi: request id seed: %w

Error message

httpapi: request id seed: %w

What it means

newIDPrefix reads 4 random bytes via crypto/rand to seed per-process request-id prefixes. If crypto/rand fails (an essentially never-seen OS entropy failure), the error is wrapped as 'httpapi: request id seed: %w'. This indicates the cryptographic entropy source is unavailable.

Source

Thrown at internal/httpapi/server.go:1926

	return slices.ContainsFunc(ips, want.Equal)
}

// hostOnly strips the port and any IPv6 brackets from a Host header value.
func hostOnly(host string) string {
	if h, _, err := net.SplitHostPort(host); err == nil {
		host = h
	}
	host = strings.TrimPrefix(host, "[")
	host = strings.TrimSuffix(host, "]")
	return strings.ToLower(host)
}

// newIDPrefix draws one random prefix per process so ids from two servers, or
// from two runs, never collide in a shared log.
func newIDPrefix() (string, error) {
	var b [4]byte
	if _, err := rand.Read(b[:]); err != nil {
		return "", fmt.Errorf("httpapi: request id seed: %w", err)
	}
	return hex.EncodeToString(b[:]), nil
}

func (s *Server) nextID() string {
	return fmt.Sprintf("%s-%06d", s.idPrefix, s.idSeq.Add(1))
}

func (s *Server) logStartup() {
	s.event("startup",
		"addr", s.Addr(),
		"mode", s.cfg.Mode,
		"db", s.dbSource(),
		"workspace", s.cfg.Workspace.RepoRoot,
		"beads_dir", s.cfg.Workspace.BeadsDir,
		"database", s.cfg.Workspace.Database,
		"host_allowlist", s.hosts.label(),
		"capabilities", strings.Join(s.ctxBody.Capabilities, ","),

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix the runtime environment so crypto/rand works (restore /dev/urandom, relax seccomp to allow getrandom)
  2. Check the wrapped cause (%w) in the error chain for the exact errno
  3. Report upstream if the sandbox legitimately cannot provide entropy — an ID prefix could tolerate weaker randomness
Defensive patterns

Strategy: try-catch

Try / catch

prefix, err := newIDPrefix()
if err != nil {
    log.Fatalf("httpapi: request id seed: %v (entropy source unavailable)", err)
}

Prevention

When it happens

Trigger: Calling newIDPrefix during server startup when rand.Read fails — e.g. getrandom(2) blocked by a seccomp/sandbox profile, a broken /dev/urandom, or an extremely constrained environment returning ENOSPC/EIO.

Common situations: Running inside hardened containers or sandboxes (gVisor, restrictive seccomp) that block getrandom; corrupted chroot images missing /dev/urandom.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/0fc1f2047d2b17d2. Report an issue: GitHub.