thanos-io/thanos · error

no external labels configured, uniquely identifying…

Error message

no external labels configured, uniquely identifying external labels must be configured; see https://thanos.io/tip/thanos/storage.md#external-labels for details.

What it means

A hard setup validation in registerBucketUploadBlocks: uploading blocks to object storage requires uniquely identifying external labels (at minimum a block 'name'-like label set), because blocks without them cannot be uniquely identified. If no --label flags are given, the command aborts before doing anything with this error.

Solutions

  1. Pass at least one external label, e.g. --label <key>="<value>" (commonly something like cluster or name).
  2. Ensure labels uniquely identify the uploader in your deployment (mirrors thanos sidecar requirements).

Example fix

// before
thanos tools bucket upload --objstore.config-file=bucket.yaml ./promdata
// after
thanos tools bucket upload --objstore.config-file=bucket.yaml --label cluster="us-east-1" ./promdata
Defensive patterns

Strategy: validation

Validate before calling

// Shell: fail fast if labels were not provided
if [ -z "$LABELS" ]; then
  echo "error: --label is required for bucket upload" >&2
  exit 1
fi
thanos tools bucket upload --objstore.config-file=bucket.yaml $LABELS ./promdata

Try / catch

if err := cmd.Run(); err != nil {
    if strings.Contains(err.Error(), "no external labels configured") {
        log.Fatal("pass at least one --label key=\"value\" flag")
    }
}

Prevention

When it happens

Trigger: Running `thanos tools bucket upload` (upload blocks) without any --label flag, i.e. tbc.labels is empty.

Common situations: Scripting the upload tool and forgetting to pass labels used elsewhere (e.g. cluster/replica), or copying a command line that omitted labels.

Understand the failure class

Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at cmd/thanos/tools_bucket.go:1465

		level.Warn(logger).Log("msg", "GLOBAL COMPACTOR SHOULD __NOT__ BE RUNNING ON THE SAME BUCKET")

		if err := compact.ApplyRetentionPolicyByResolution(ctx, logger, insBkt, sy.Metas(), retentionByResolution, stubCounter); err != nil {
			return errors.Wrap(err, "retention failed")
		}
		return nil
	})
}

func registerBucketUploadBlocks(app extkingpin.AppClause, objStoreConfig *extflag.PathOrContent) {
	cmd := app.Command("upload-blocks", "Upload blocks push blocks from the provided path to the object storage.")

	tbc := &bucketUploadBlocksConfig{}
	tbc.registerBucketUploadBlocksFlag(cmd)

	cmd.Setup(func(g *run.Group, logger log.Logger, reg *prometheus.Registry, _ opentracing.Tracer, _ <-chan struct{}, _ bool) error {
		if len(tbc.labels) == 0 {
			return errors.New("no external labels configured, uniquely identifying external labels must be configured; see https://thanos.io/tip/thanos/storage.md#external-labels for details.")
		}

		lset, err := parseFlagLabels(tbc.labels)
		if err != nil {
			return errors.Wrap(err, "unable to parse external labels")
		}
		if err := promclient.IsDirAccessible(tbc.path); err != nil {
			return errors.Wrapf(err, "unable to access path '%s'", tbc.path)
		}

		confContentYaml, err := objStoreConfig.Content()
		if err != nil {
			return errors.Wrap(err, "unable to parse objstore config")
		}

		bkt, err := client.NewBucket(logger, confContentYaml, component.Upload.String(), nil)
		if err != nil {
			return errors.Wrap(err, "unable to create bucket")

View on GitHub (pinned to 35b8b99117)