thanos-io/thanos · error
expected 4 components in config metadata, and received
Error message
expected 4 components in config metadata, and received %d, meta: %s
What it means
After reading the first line of the memcached cluster CONFIG response, parseConfig splits it on spaces and expects exactly 4 components ('CONFIG cluster 0 <size>'). If the metadata line has a different number of space-separated tokens, the response does not conform to the protocol and this error is returned with the offending line embedded.
Solutions
- Confirm the endpoint is a cluster-mode ElastiCache / memcached cluster answering 'CONFIG cluster ...'.
- Inspect the raw first line (included in the error message) to identify the unexpected response.
- Remove proxies or middlewares that alter the protocol response.
- Fix test mocks to emit exactly 'CONFIG cluster 0 <len>\r\n'.
Example fix
// before
// server replies: "ERROR unsupported command" -> 2 components
// after: validate endpoint mode first
if !isClusterModeEndpoint(addr) {
return nil, errors.New("memcached auto-discovery requires a cluster-mode endpoint")
} Defensive patterns
Strategy: validation
Validate before calling
func looksLikeConfigMeta(line string) bool {
parts := strings.Fields(line)
return len(parts) == 4 && parts[0] == "CONFIG" && parts[1] == "cluster"
} Try / catch
cfg, err := discovery.parseConfig(reader)
if err != nil && strings.Contains(err.Error(), "expected 4 components") {
return nil, fmt.Errorf("endpoint %s is not answering the cluster CONFIG protocol: %w", addr, err)
} Prevention
- Confirm cluster-mode (ElastiCache 'cluster enabled') before enabling auto-discovery.
- Probe the endpoint with a manual 'config get cluster\r\n' before wiring discovery.
- Keep mock servers in tests byte-exact with the real protocol.
- Route around proxies that rewrite plain-text memcached responses.
When it happens
Trigger: The server's first response line is not 'CONFIG cluster 0 <len>' — e.g. an ERROR/CLIENT_ERROR reply from a non-cluster memcached, a truncated/corrupt response, or extra/missing tokens from a protocol-incompatible endpoint.
Common situations: Connecting to plain memcached (returns 'ERROR' to 'config get'), ElastiCache in non-cluster (replica) mode, or a custom/mock server emitting malformed metadata.
Related errors
- failed to read config metadata
- failed to parse config size from metadata
- failed to parser config version
- failed to read nodes
- expected in config payload, but got instead
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/5bb6eee6adf3eaee.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/discovery/memcache/resolver.go:72
return nil, err
}
return config, err
}
func (s *memcachedAutoDiscovery) parseConfig(reader *bufio.Reader) (*clusterConfig, error) {
clusterConfig := new(clusterConfig)
configMeta, err := reader.ReadString('\n')
if err != nil {
return nil, fmt.Errorf("failed to read config metadata: %s", err)
}
configMeta = strings.TrimSpace(configMeta)
// First line should be "CONFIG cluster 0 [length-of-payload-]
configMetaComponents := strings.Split(configMeta, " ")
if len(configMetaComponents) != 4 {
return nil, fmt.Errorf("expected 4 components in config metadata, and received %d, meta: %s", len(configMetaComponents), configMeta)
}
configSize, err := strconv.Atoi(configMetaComponents[3])
if err != nil {
return nil, fmt.Errorf("failed to parse config size from metadata: %s, error: %s", configMeta, err)
}
configVersion, err := reader.ReadString('\n')
if err != nil {
return nil, fmt.Errorf("failed to find config version: %s", err)
}
clusterConfig.version, err = strconv.Atoi(strings.TrimSpace(configVersion))
if err != nil {
return nil, fmt.Errorf("failed to parser config version: %s", err)
}
nodes, err := reader.ReadString('\n')
if err != nil {View on GitHub (pinned to 35b8b99117)