{"record":{"id":"bfa02c90784bf564","repo":"juanfont/headscale","slug":"reaching-headscale-container-w","errorCode":null,"errorMessage":"reaching headscale container: %w","messagePattern":"reaching headscale container: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"integration/scenario.go","lineNumber":487,"sourceCode":"\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif headscale, ok := s.controlServers.Load(\"headscale\"); ok {\n\t\treturn headscale, nil\n\t}\n\n\tif usePostgresForTest {\n\t\topts = append(opts, hsic.WithPostgres())\n\t}\n\n\theadscale, err := hsic.New(s.pool, s.Networks(), opts...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating headscale container: %w\", err)\n\t}\n\n\terr = headscale.WaitForRunning()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reaching headscale container: %w\", err)\n\t}\n\n\ts.controlServers.Store(\"headscale\", headscale)\n\n\treturn headscale, nil\n}\n\n// Pool returns the [dockertest.Pool] for the scenario.\nfunc (s *Scenario) Pool() *dockertest.Pool {\n\treturn s.pool\n}\n\n// GetOrCreateUser gets or creates a user in the [Scenario].\nfunc (s *Scenario) GetOrCreateUser(userStr string) *User {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif user, ok := s.users[userStr]; ok {","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/integration/scenario.go#L469-L505","documentation":"Returned by Scenario.Headscale when the freshly created headscale container starts but never becomes reachable — headscale.WaitForRunning() polls the server's health/ready endpoint and timed out. It means the container exists but headscale inside it is not serving.","triggerScenarios":"Calling any Scenario helper that triggers s.Headscale() when the headscale process inside the container crashes on startup, listens on a different address, or the health check cannot reach the port (network attachment issues).","commonSituations":"Broken headscale config mounted into the container (bad TLS certs, invalid noise key, unreachable DB); headscale binary/image version mismatch where the config keys changed; Postgres option enabled but the DB container is not ready; slow CI machine hitting the readiness timeout.","solutions":["Dump the container logs right after failure: `docker logs <headscale-container>` — headscale usually logs the fatal config error","If using WithPostgres, verify the database container became healthy before headscale starts","Regenerate certs/keys if the test mounts stale or mismatched TLS material","On slow machines, retry the run once — but if it repeats, treat it as a config/code defect per the repo's flake policy"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"headscale, err := scenario.Headscale()\nif err != nil {\n    // pull container logs immediately — WaitForRunning failures are almost always\n    // a startup crash visible in stderr\n    t.Fatalf(\"headscale not ready: %v — check container logs\", err)\n}","preventionTips":["Always dump control-container logs on readiness timeout","Validate mounted config (certs, keys, DB settings) before the run","Pre-warm dependencies (e.g. Postgres) before headscale starts"],"tags":["docker","headscale","health-check","integration-test","startup"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}