thanos-io/thanos · error

failed to parse config size from metadata

Error message

failed to parse config size from metadata: %s, error: %s

What it means

The 4th token of the CONFIG metadata line is the payload byte length and must be a decimal integer. parseConfig parses it with strconv.Atoi; if it is not a valid integer (empty or non-numeric), this error is returned showing the full metadata line and the strconv error. It indicates a malformed or corrupted CONFIG response header.

Solutions

  1. Fix the server/mock to emit a decimal byte length as the 4th token.
  2. Check for stream corruption: verify TLS/plain-text expectations and remove transforming proxies.
  3. Log and compare the metadata line against the spec 'CONFIG cluster 0 <len>'.
  4. Update test fixtures to include a valid numeric size.

Example fix

// before
// response: "CONFIG cluster 0 1f2e" -> strconv.Atoi fails
// after
fmt.Fprintf(w, "CONFIG cluster 0 %d\r\n", len(payload))
Defensive patterns

Strategy: validation

Validate before calling

func validConfigSize(meta string) error {
    parts := strings.Fields(meta)
    if len(parts) != 4 {
        return fmt.Errorf("bad meta %q", meta)
    }
    _, err := strconv.Atoi(parts[3])
    return err
}

Try / catch

if err := validConfigSize(metaLine); err != nil {
    return nil, fmt.Errorf("malformed CONFIG header from %s: %w", addr, err)
}

Prevention

When it happens

Trigger: The metadata line splits into 4 components but the last is non-numeric, e.g. 'CONFIG cluster 0 abc' or a mangled/interleaved response where the length token is corrupted.

Common situations: Corrupted TCP stream framing; a proxy injecting text into the response; custom servers writing the length in hex or with a suffix; hand-written malformed fixtures in tests.

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/80f53dd233690b26. Report an issue: GitHub.

Appendix: source

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

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 {
		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))

View on GitHub (pinned to 35b8b99117)