thanos-io/thanos · error

conflict

Error message

conflict

What it means

errConflict is the sentinel returned by Write and receiveOTLPHTTP whenever a write fails due to a conflict-type error (e.g. the target considers the series/operation conflicting). The HTTP handler maps it to http.StatusConflict (409) and the capnp server maps it to writecapnp.WriteError_alreadyExists. It is matched with errors.Cause, so it must be the root cause of the returned error.

Solutions

  1. Check which peer returned the conflict and inspect its logs for the underlying store error
  2. Make the write idempotent on the client or deduplicate retries before resending
  3. Verify all receiver replicas share a consistent hashring configuration so conflicting writes don't occur
  4. If you need programmatic handling, compare with errors.Cause(err) == errConflict / errors.Is where wrapping permits

Example fix

// before
if err := r.Write(ctx, req); err != nil { return err }
// after
if err := r.Write(ctx, req); err != nil {
    if errors.Is(errors.Cause(err), errConflict) {
        return status.Error(codes.AlreadyExists, err.Error())
    }
    return err
}
Defensive patterns

Strategy: try-catch

Type guard

func isConflict(err error) bool {
    return errors.Is(errors.Cause(err), errConflict)
}

Try / catch

err := r.Write(ctx, req)
if err != nil {
    switch errors.Cause(err) {
    case errConflict: http.Error(w, err.Error(), http.StatusConflict)
    default: http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

Prevention

When it happens

Trigger: Write or receiveOTLPHTTP returns an error whose root cause is errConflict — a replication target or local store reports a conflicting write that is not a validation, unavailability, or bad-replica error.

Common situations: Duplicate/overlapping writes racing on the same series, miswired replication producing out-of-order conflicting state between receiver replicas, clients retrying writes the target already committed.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at pkg/receive/handler.go:89

	// AllTenantsQueryParam is the query parameter for getting TSDB stats for all tenants.
	AllTenantsQueryParam = "all_tenants"
	// LimitStatsQueryParam is the query parameter for limiting the amount of returned TSDB stats.
	LimitStatsQueryParam = "limit"
	// Labels for metrics.
	labelSuccess = "success"
	labelError   = "error"
)

type ReplicationProtocol string

const (
	ProtobufReplication  ReplicationProtocol = "protobuf"
	CapNProtoReplication ReplicationProtocol = "capnproto"
)

var (
	// errConflict is returned whenever an operation fails due to any conflict-type error.
	errConflict = errors.New("conflict")

	errBadReplica  = errors.New("request replica exceeds receiver replication factor")
	errNotReady    = errors.New("target not ready")
	errUnavailable = errors.New("target not available")

	errValidation = errors.New("validation error")
)

type WriteableStoreAsyncClient interface {
	storepb.WriteableStoreClient
	RemoteWriteAsync(context.Context, *storepb.WriteRequest, endpointReplica, []int, chan writeResponse, func(error))
	// TryRemoteWriteAsync submits the request without blocking. Returns false if the peer's
	// worker pool is at capacity; the caller should fall back to RemoteWriteAsync.
	TryRemoteWriteAsync(context.Context, *storepb.WriteRequest, endpointReplica, []int, chan writeResponse, func(error)) bool
}

// Options for the web Handler.
type Options struct {

View on GitHub (pinned to 35b8b99117)