thanos-io/thanos · error

failed to parser config version

Error message

failed to parser config version: %s

What it means

The version line read from the CONFIG payload must be a decimal integer. parseConfig converts it with strconv.Atoi after trimming whitespace; on failure this error is returned (note the 'parser' typo in the message itself). It signals the payload stream is misaligned — the bytes expected to be the version line are not a number.

Solutions

  1. Verify payload framing: the metadata size must exactly match the version+nodes line bytes.
  2. Ensure the server writes the version as a bare decimal line (e.g. '1\r\n').
  3. Check for connection multiplexing/proxying that could interleave other responses.
  4. Fix test fixtures to include a numeric version line.

Example fix

// before
// payload: "version-1\nhost1|ip|port\n" -> Atoi("version-1") fails
// after
fmt.Fprintf(w, "CONFIG cluster 0 %d\r\n1\r\n%s\r\n", len(payload), payload)
Defensive patterns

Strategy: validation

Validate before calling

func validVersionLine(line string) error {
    _, err := strconv.Atoi(strings.TrimSpace(line))
    return err
}

Try / catch

cfg, err := discovery.parseConfig(reader)
if err != nil && strings.Contains(err.Error(), "config version") {
    return nil, fmt.Errorf("misaligned CONFIG payload from %s; check framing", addr)
}

Prevention

When it happens

Trigger: The line following the metadata is non-numeric, e.g. because a wrong configSize token caused ReadString('\n') to capture the wrong bytes, or the server emitted a status/error string instead of the version.

Common situations: Off-by-N framing errors shifting the parse position; custom servers writing the version with a prefix/suffix; corrupt or interleaved responses on a shared connection.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/bdf68faa78349431. Report an issue: GitHub.

Appendix: source

Thrown at pkg/discovery/memcache/resolver.go:86

	// 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 {
		return nil, fmt.Errorf("failed to read nodes: %s", err)
	}

	if len(configVersion)+len(nodes) != configSize {
		return nil, fmt.Errorf("expected %d in config payload, but got %d instead", configSize, len(configVersion)+len(nodes))
	}

	for host := range strings.SplitSeq(strings.TrimSpace(nodes), " ") {
		dnsIpPort := strings.Split(host, "|")
		if len(dnsIpPort) != 3 {
			return nil, fmt.Errorf("node not in expected format: %s", dnsIpPort)
		}
		port, err := strconv.Atoi(dnsIpPort[2])
		if err != nil {

View on GitHub (pinned to 35b8b99117)