{"record":{"id":"0fc1f2047d2b17d2","repo":"gastownhall/beads","slug":"httpapi-request-id-seed-w","errorCode":null,"errorMessage":"httpapi: request id seed: %w","messagePattern":"httpapi: request id seed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/httpapi/server.go","lineNumber":1926,"sourceCode":"\treturn slices.ContainsFunc(ips, want.Equal)\n}\n\n// hostOnly strips the port and any IPv6 brackets from a Host header value.\nfunc hostOnly(host string) string {\n\tif h, _, err := net.SplitHostPort(host); err == nil {\n\t\thost = h\n\t}\n\thost = strings.TrimPrefix(host, \"[\")\n\thost = strings.TrimSuffix(host, \"]\")\n\treturn strings.ToLower(host)\n}\n\n// newIDPrefix draws one random prefix per process so ids from two servers, or\n// from two runs, never collide in a shared log.\nfunc newIDPrefix() (string, error) {\n\tvar b [4]byte\n\tif _, err := rand.Read(b[:]); err != nil {\n\t\treturn \"\", fmt.Errorf(\"httpapi: request id seed: %w\", err)\n\t}\n\treturn hex.EncodeToString(b[:]), nil\n}\n\nfunc (s *Server) nextID() string {\n\treturn fmt.Sprintf(\"%s-%06d\", s.idPrefix, s.idSeq.Add(1))\n}\n\nfunc (s *Server) logStartup() {\n\ts.event(\"startup\",\n\t\t\"addr\", s.Addr(),\n\t\t\"mode\", s.cfg.Mode,\n\t\t\"db\", s.dbSource(),\n\t\t\"workspace\", s.cfg.Workspace.RepoRoot,\n\t\t\"beads_dir\", s.cfg.Workspace.BeadsDir,\n\t\t\"database\", s.cfg.Workspace.Database,\n\t\t\"host_allowlist\", s.hosts.label(),\n\t\t\"capabilities\", strings.Join(s.ctxBody.Capabilities, \",\"),","sourceCodeStart":1908,"sourceCodeEnd":1944,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/httpapi/server.go#L1908-L1944","documentation":"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.","triggerScenarios":"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.","commonSituations":"Running inside hardened containers or sandboxes (gVisor, restrictive seccomp) that block getrandom; corrupted chroot images missing /dev/urandom.","solutions":["Fix the runtime environment so crypto/rand works (restore /dev/urandom, relax seccomp to allow getrandom)","Check the wrapped cause (%w) in the error chain for the exact errno","Report upstream if the sandbox legitimately cannot provide entropy — an ID prefix could tolerate weaker randomness"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"prefix, err := newIDPrefix()\nif err != nil {\n    log.Fatalf(\"httpapi: request id seed: %v (entropy source unavailable)\", err)\n}","preventionTips":["Ensure /dev/urandom exists and getrandom(2) is permitted in your sandbox/seccomp profile","Test server startup in the production container image early","Treat this as an environment-level failure, not retryable in-process"],"tags":["crypto","entropy","startup","httpapi"],"backgroundTag":"crypto-rand-unavailable","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}