thanos-io/thanos · error

parsing downstream tripper config YAML file

Error message

parsing downstream tripper config YAML file

What it means

This error is returned by parseTransportConfiguration when yaml.UnmarshalStrict fails to decode the downstream tripper config YAML into queryfrontend.DownstreamTripperConfig. UnmarshalStrict is used, so unknown fields also fail. It wraps the underlying YAML/field error for diagnosis.

Solutions

  1. Validate the YAML syntax (yamllint) and fix indentation/tabs.
  2. Remove unknown fields; strict unmarshalling rejects any key not in DownstreamTripperConfig.
  3. Check field types: durations like idle_conn_timeout must be valid duration strings.
  4. Read the wrapped underlying error to identify the exact offending line/field.

Example fix

// before (unknown field, fails strict unmarshal)
idle_conn_timeout: 90s
max_idle_conns_per_host: 100
unknown_field: true
// after
idle_conn_timeout: 90s
max_idle_conns_per_host: 100
Defensive patterns

Strategy: validation

Validate before calling

var probe map[string]any
if err := yaml.Unmarshal(raw, &probe); err != nil {
  return fmt.Errorf("downstream tripper YAML invalid: %w", err)
}

Try / catch

cfg := &queryfrontend.DownstreamTripperConfig{}
if err := yaml.UnmarshalStrict(content, cfg); err != nil {
  log.Fatalf("bad downstream tripper config: %v", err)
}

Prevention

When it happens

Trigger: Providing --downstream-tripper-config-file or --downstream-tripper-config content that is invalid YAML or contains fields not present in DownstreamTripperConfig (strict unmarshalling rejects unknown keys).

Common situations: Copied Cortex config with unsupported keys, YAML tabs instead of spaces, wrong types (e.g. string where a duration is expected), or leftover fields after a Thanos version upgrade.

Related errors


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

Appendix: source

Thrown at cmd/thanos/query_frontend.go:206

func parseTransportConfiguration(downstreamTripperConfContentYaml []byte) (*http.Transport, error) {
	downstreamTripper := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
			DualStack: true,
		}).DialContext,
		ForceAttemptHTTP2:     true,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}

	if len(downstreamTripperConfContentYaml) > 0 {
		tripperConfig := &queryfrontend.DownstreamTripperConfig{}
		if err := yaml.UnmarshalStrict(downstreamTripperConfContentYaml, tripperConfig); err != nil {
			return nil, errors.Wrap(err, "parsing downstream tripper config YAML file")
		}

		if tripperConfig.TLSConfig != nil {
			tlsConfig, err := exthttp.NewTLSConfig(tripperConfig.TLSConfig)
			if err != nil {
				return nil, errors.Wrap(err, "parsing downstream tripper TLS config YAML")
			}
			downstreamTripper.TLSClientConfig = tlsConfig
		}
		if tripperConfig.IdleConnTimeout > 0 {
			downstreamTripper.IdleConnTimeout = time.Duration(tripperConfig.IdleConnTimeout)
		}
		if tripperConfig.ResponseHeaderTimeout > 0 {
			downstreamTripper.ResponseHeaderTimeout = time.Duration(tripperConfig.ResponseHeaderTimeout)
		}
		if tripperConfig.TLSHandshakeTimeout > 0 {
			downstreamTripper.TLSHandshakeTimeout = time.Duration(tripperConfig.TLSHandshakeTimeout)
		}

View on GitHub (pinned to 35b8b99117)