{"record":{"id":"d0e32fc8955b2d3d","repo":"juanfont/headscale","slug":"derper-is-not-ready-w","errorCode":null,"errorMessage":"DERPer is not ready: %w","messagePattern":"DERPer is not ready: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integration/dsic/dsic.go","lineNumber":351,"sourceCode":"\n// GetDERPPort returns the DERP port of the DERPer instance.\nfunc (t *DERPServerInContainer) GetDERPPort() int {\n\treturn t.derpPort\n}\n\n// WaitForRunning blocks until the DERPer instance is ready to be used.\nfunc (t *DERPServerInContainer) WaitForRunning() error {\n\turl := \"https://\" + net.JoinHostPort(t.GetHostname(), strconv.Itoa(t.GetDERPPort())) + \"/\"\n\tlog.Printf(\"waiting for DERPer to be ready at %s\", url)\n\n\tinsecureTransport := http.DefaultTransport.(*http.Transport).Clone()      //nolint\n\tinsecureTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint\n\tclient := &http.Client{Transport: insecureTransport}\n\n\treturn t.pool.Retry(func() error {\n\t\tresp, err := client.Get(url) //nolint\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"DERPer is not ready: %w\", err)\n\t\t}\n\n\t\tif resp.StatusCode != http.StatusOK {\n\t\t\treturn errDERPerStatusCodeNotOk\n\t\t}\n\n\t\treturn nil\n\t})\n}\n\n// ConnectToNetwork connects the DERPer instance to a network.\nfunc (t *DERPServerInContainer) ConnectToNetwork(network *dockertest.Network) error {\n\treturn t.container.ConnectToNetwork(network)\n}\n\n// WriteFile save file inside the container.\nfunc (t *DERPServerInContainer) WriteFile(path string, data []byte) error {\n\treturn integrationutil.WriteFileToContainer(t.pool, t.container, path, data)","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/integration/dsic/dsic.go#L333-L369","documentation":"Returned inside the pool.Retry closure of DERPServerInContainer.WaitForRunning when the HTTPS probe against the DERPer fails at the transport level (connection refused, TLS handshake incomplete, DNS not resolvable). dockertest retries it with backoff; if the DERPer never comes up, this error surfaces.","triggerScenarios":"After starting the DERPer container, probing https://<hostname>:443/ fails repeatedly — server not yet listening, container networking broken, or the DERPer process crashed so the port never opens.","commonSituations":"DERPer exits due to bad flags or cert problems; Docker network/DNS not propagated so the hostname doesn't resolve; overloaded CI hosts making startup exceed the retry budget.","solutions":["Inspect DERPer container logs to confirm the process started and bound 443","Verify the container is attached to the expected Docker network and DNS resolution works between containers","Increase available resources on the CI host or reduce parallelism so startup fits the retry window"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// WaitForRunning already retries; guard only against terminal timeout\nif err := derp.WaitForRunning(); err != nil {\n    log, _ := derp.SaveLog(\"/tmp/control\")\n    t.Fatalf(\"derp never became ready; logs at %s: %v\", log, err)\n}","preventionTips":["Always capture DERPer logs on readiness failure instead of guessing","Reserve capacity on CI hosts; overloaded Docker breaks readiness windows"],"tags":["integration-test","derp","network","docker"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}