thanos-io/thanos · error

unable to parse external labels

Error message

unable to parse external labels

What it means

Wraps a failure from parseFlagLabels when the --label flags cannot be parsed into valid Prometheus labels. Labels must be key="value" pairs with valid label-name and label-value characters; invalid syntax causes this wrapped error.

Solutions

  1. Check the wrapped error for the offending label and fix its syntax: --label key="value".
  2. Quote labels in the shell so values with special characters survive (single-quote the whole flag argument).
  3. Ensure label names match [a-zA-Z_][a-zA-Z0-9_]* and values are valid UTF-8 label values.
  4. Avoid duplicate keys across --label flags.

Example fix

// before
--label cluster=us-east 1        # space breaks parsing
// after
--label 'cluster="us-east-1"'   # properly quoted key="value"
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate label pairs before passing to the CLI
func validLabel(l string) bool {
    parts := strings.SplitN(l, "=", 2)
    if len(parts) != 2 { return false }
    return labels.IsValidName(parts[0]) && utf8.ValidString(parts[1])
}

Try / catch

if err := runUpload(labels); err != nil {
    if strings.Contains(err.Error(), "unable to parse external labels") {
        log.Fatalf("bad --label syntax, use --label key=\"value\" with valid label names: %v", err)
    }
}

Prevention

When it happens

Trigger: Passing --label values that are not valid key=value pairs, contain invalid characters, duplicate keys, or wrong quoting (e.g. unquoted values with spaces, or '=' in the key).

Common situations: Shell quoting stripping double quotes so values contain spaces or bad chars, using invalid label names (starting with digits, special characters), or passing an empty --label flag.

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

Appendix: source

Thrown at cmd/thanos/tools_bucket.go:1470

		}
		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")
		}

		bkt = objstoretracing.WrapWithTraces(objstore.WrapWithMetrics(bkt, extprom.WrapRegistererWithPrefix("thanos_", reg), bkt.Name()))

		tbcDir, err := os.OpenRoot(tbc.path)

View on GitHub (pinned to 35b8b99117)