thanos-io/thanos · error

marshal content of cache backend configuration

Error message

marshal content of cache backend configuration

What it means

After parsing the index cache config, NewIndexCache re-marshals cacheConfig.Config (the opaque backend-specific sub-config) back to YAML to pass to the backend constructor (memcached, redis, etc.). This error is thrown when that in-memory value cannot be marshaled, which is essentially impossible for config-derived data and usually indicates an internal bug or an unsupported value type in Config.

Solutions

  1. Inspect what is placed into cacheConfig.Config; ensure only YAML-serializable types are set.
  2. Upgrade or patch Thanos — if triggered by stock YAML input this indicates a bug; file an issue.
  3. As a workaround, pass backend config as plain YAML bytes instead of pre-parsed structures.
Defensive patterns

Strategy: try-catch

Try / catch

cache, err := storecache.NewIndexCache(logger, confYaml, reg)
if err != nil && strings.Contains(err.Error(), "marshal content of cache backend configuration") {
	logger.Error("internal cache-config marshal failure; check programmatic Config values", "err", err)
}

Prevention

When it happens

Trigger: Calling NewIndexCache where the decoded cacheConfig.Config field holds a value that yaml.Marshal cannot serialize (e.g. a custom type with no marshaler containing channel/func values injected programmatically rather than via YAML).

Common situations: Programmatic construction of IndexCacheConfig in tests or wrappers stuffing non-serializable values into Config; custom forks adding unsupported field types; virtually never hit from plain YAML files since the value just came from Unmarshal.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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

Appendix: source

Thrown at pkg/store/cache/factory.go:51

	// Available item types are Postings, Series and ExpandedPostings.
	EnabledItems []string `yaml:"enabled_items"`
	// TTL for storing items in remote cache. Not supported for inmemory cache.
	// Default value is 24h.
	TTL time.Duration `yaml:"ttl"`
}

// NewIndexCache initializes and returns new index cache.
func NewIndexCache(logger log.Logger, confContentYaml []byte, reg prometheus.Registerer) (IndexCache, error) {
	level.Info(logger).Log("msg", "loading index cache configuration")
	cacheConfig := &IndexCacheConfig{}
	cacheMetrics := NewCommonMetrics(reg)
	if err := yaml.UnmarshalStrict(confContentYaml, cacheConfig); err != nil {
		return nil, errors.Wrap(err, "parsing config YAML file")
	}

	backendConfig, err := yaml.Marshal(cacheConfig.Config)
	if err != nil {
		return nil, errors.Wrap(err, "marshal content of cache backend configuration")
	}

	if cacheConfig.TTL == 0 {
		cacheConfig.TTL = memcachedDefaultTTL
	}

	var cache IndexCache
	switch strings.ToUpper(string(cacheConfig.Type)) {
	case string(INMEMORY):
		cache, err = NewInMemoryIndexCache(logger, cacheMetrics, reg, backendConfig)
	case string(MEMCACHED):
		var memcached cacheutil.RemoteCacheClient
		memcached, err = cacheutil.NewMemcachedClient(logger, "index-cache", backendConfig, reg)
		if err == nil {
			cache, err = NewRemoteIndexCache(logger, memcached, cacheMetrics, reg, cacheConfig.TTL)
		}
	case string(REDIS):
		var redisCache cacheutil.RemoteCacheClient

View on GitHub (pinned to 35b8b99117)