{"record":{"id":"a34291d10c8a8aa5","repo":"t8y2/dbx","slug":"etcd-connection-error-w","errorCode":null,"errorMessage":"etcd connection error: %w","messagePattern":"etcd connection error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/etcd2-go/client.go","lineNumber":320,"sourceCode":"\t\treader = strings.NewReader(body)\n\t}\n\treq, err := http.NewRequestWithContext(ctx, method, strings.TrimSuffix(endpoint, \"/\")+path, reader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif c.username != \"\" {\n\t\treq.SetBasicAuth(c.username, c.password)\n\t}\n\tfor key, value := range header {\n\t\treq.Header.Set(key, value)\n\t}\n\tif body != \"\" && req.Header.Get(\"Content-Type\") == \"\" {\n\t\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\t}\n\tresponse, err := c.http.Do(req)\n\tif err != nil {\n\t\t// gRPC-style sentinel so the host-side transient-error handling keeps working.\n\t\treturn nil, fmt.Errorf(\"etcd connection error: %w\", err)\n\t}\n\treturn response, nil\n}\n\n// doAt performs a v2 API request against a specific endpoint.\nfunc (c *authenticatedClient) doAt(ctx context.Context, method, endpoint, path, body string) ([]byte, *http.Response, error) {\n\tresponse, err := c.requestAt(ctx, method, endpoint, path, body, nil)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tpayload, readErr := io.ReadAll(response.Body)\n\t_ = response.Body.Close()\n\tif response.StatusCode < 200 || response.StatusCode >= 300 {\n\t\treturn nil, response, errorFromResponse(response.StatusCode, payload)\n\t}\n\tif readErr != nil {\n\t\treturn nil, response, readErr\n\t}","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/etcd2-go/client.go#L302-L338","documentation":"requestAt wraps any transport-level failure of the HTTP request (DNS failure, connection refused/reset, TLS handshake error, timeout) into the sentinel-prefixed error 'etcd connection error: %w'. It is deliberately gRPC-style so host-side transient-error handling can keep classifying it as a connection problem. No HTTP response was received at all.","triggerScenarios":"Any v2 API call (via request or doAt) where c.http.Do fails: endpoint unreachable, port closed, TLS mismatch, network partition, or context deadline exceeded.","commonSituations":"etcd not running on the configured host:port, wrong port (2379 client vs 2380 peer), firewall blocking, TLS config pointing at a plaintext endpoint or vice versa, container networking issues.","solutions":["Inspect the wrapped %w cause to distinguish refused vs timeout vs TLS failure.","Verify the endpoint is reachable: curl http://host:2379/version (or https as configured).","Confirm the client port 2379 (not the peer port 2380) and correct scheme http vs https.","Retry with backoff for transient network conditions; the prefix supports the library's transient-error classification."],"exampleFix":"// before\nendpoint = \"https://127.0.0.1:2379\" // server has no TLS\n// after\nendpoint = \"http://127.0.0.1:2379\"","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", host, 2*time.Second)\nif err != nil { return fmt.Errorf(\"etcd endpoint %s unreachable: %v\", host, err) }\nconn.Close()","typeGuard":null,"tryCatchPattern":"_, err := client.request(ctx, \"GET\", \"/keys/foo\")\nif err != nil && strings.HasPrefix(err.Error(), \"etcd connection error:\") {\n    return retryWithBackoff(ctx, 5, func() error { _, err := client.request(ctx, \"GET\", \"/keys/foo\"); return err })\n}","preventionTips":["Pre-flight TCP check of host:2379","Match scheme (http/https) to server TLS config","Rely on the sentinel prefix for transient-error classification instead of string-matching the cause"],"tags":["etcd","network","connection"],"backgroundTag":"connection-refused","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}