{"record":{"id":"8aaac75f21e42290","repo":"thanos-io/thanos","slug":"failed-to-read-config-metadata-s","errorCode":null,"errorMessage":"failed to read config metadata: %s","messagePattern":"failed to read config metadata: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/discovery/memcache/resolver.go","lineNumber":65,"sourceCode":"\t}\n\tif err := rw.Flush(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tconfig, err = s.parseConfig(rw.Reader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn config, err\n}\n\nfunc (s *memcachedAutoDiscovery) parseConfig(reader *bufio.Reader) (*clusterConfig, error) {\n\tclusterConfig := new(clusterConfig)\n\n\tconfigMeta, err := reader.ReadString('\\n')\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read config metadata: %s\", err)\n\t}\n\tconfigMeta = strings.TrimSpace(configMeta)\n\n\t// First line should be \"CONFIG cluster 0 [length-of-payload-]\n\tconfigMetaComponents := strings.Split(configMeta, \" \")\n\tif len(configMetaComponents) != 4 {\n\t\treturn nil, fmt.Errorf(\"expected 4 components in config metadata, and received %d, meta: %s\", len(configMetaComponents), configMeta)\n\t}\n\n\tconfigSize, err := strconv.Atoi(configMetaComponents[3])\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse config size from metadata: %s, error: %s\", configMeta, err)\n\t}\n\n\tconfigVersion, err := reader.ReadString('\\n')\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to find config version: %s\", err)\n\t}","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/discovery/memcache/resolver.go#L47-L83","documentation":"The memcached auto-discovery client fetches cluster configuration via the memcached 'config get cluster' protocol, whose first line is metadata ('CONFIG cluster 0 <len>'). parseConfig reads that first line with bufio.Reader.ReadString('\\n'); this error is returned when the read fails — typically EOF because the stream ended before any newline, or a connection error.","triggerScenarios":"Calling Resolve on memcachedAutoDiscovery when the server or connection returns an empty/short payload: connection closed before any data, a non-cluster memcached replying without a newline, or an I/O error on the socket.","commonSituations":"Pointing discovery at a plain (non-cluster-mode) memcached or ElastiCache node that does not support the cluster config command; network disconnects mid-request; proxies buffering or stripping the CONFIG response.","solutions":["Verify the target is a cluster-enabled ElastiCache/memcached endpoint that supports 'config get cluster'.","Check network connectivity and whether the connection closes prematurely (timeouts, proxies, LB idle timeouts).","Inspect the underlying error embedded via %s (io.EOF vs socket error) to narrow the cause.","Wrap Resolve with retry/backoff for transient connection resets."],"exampleFix":"// before\ncfg, err := discovery.parseConfig(bufio.NewReader(conn)) // EOF: server closed early\n// after\nconn.SetDeadline(time.Now().Add(5 * time.Second))\ncfg, err := discovery.parseConfig(bufio.NewReader(conn))\nif err != nil {\n    return nil, fmt.Errorf(\"cluster config fetch failed (cluster-mode endpoint?): %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"func canFetchConfig(conn net.Conn) error {\n    conn.SetReadDeadline(time.Now().Add(5 * time.Second))\n    return nil // also verify endpoint is cluster-mode before discovery\n}","typeGuard":null,"tryCatchPattern":"cfg, err := discovery.parseConfig(reader)\nif err != nil {\n    if errors.Is(err, io.EOF) || strings.Contains(err.Error(), \"failed to read config metadata\") {\n        return nil, fmt.Errorf(\"endpoint %s closed connection before config metadata; is it cluster-mode?\", addr)\n    }\n    return nil, err\n}","preventionTips":["Only use auto-discovery against cluster-mode ElastiCache/memcached endpoints.","Set explicit read deadlines so dead connections fail fast and retryably.","Monitor connection resets between client and the cache tier.","Log the underlying error to distinguish EOF from socket failures."],"tags":["memcached","elasticache","protocol","io"],"backgroundTag":"file-read-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}