hashicorp/terraform · error

secret_suffix must not end with

Error message

secret_suffix must not end with '-<number>', got %q

What it means

Validation error during backend Configure: secret_suffix ends with a '-<number>' segment (backend.go:328-336). The k8s backend appends its own '-part-N' numeric suffix when chunking large state across multiple Secrets; a user-supplied numeric suffix would collide with that scheme, so it is rejected up front.

Solutions

  1. Change secret_suffix so its last '-' segment is non-numeric, e.g., "foo-state" instead of "foo-1".
  2. If you need uniqueness, use letters/words in the final segment.
  3. After fixing, re-run terraform init to re-configure the backend.

Example fix

// before
terraform {
  backend "kubernetes" {
    secret_suffix = "myteam-7"
  }
}
// after
terraform {
  backend "kubernetes" {
    secret_suffix = "myteam-prod"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate secret_suffix before applying the backend:
// if hasNumericSuffix(suffix, "-") {
//   return fmt.Errorf("secret_suffix must not end with '-<number>', got %q", suffix)
// }

Prevention

When it happens

Trigger: Setting secret_suffix = "foo-1" or secret_suffix = "team-42" — anything where the final '-'-delimited segment is purely numeric. The check hasNumericSuffix(b.nameSuffix, "-") returns true.

Common situations: Copying a numeric convention from another backend; auto-generating suffixes with a numeric ID; renaming a workspace and appending a number.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/65af2a4e8068ccc9. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/remote-state/kubernetes/backend.go:334

			kV, vV := it.Element()
			if vV.IsNull() {
				vV = cty.StringVal("")
			}
			labels[kV.AsString()] = vV.AsString()
		}
		b.labels = labels
	}

	ns := data.String("namespace")
	b.namespace = ns

	b.nameSuffix = data.String("secret_suffix")
	if hasNumericSuffix(b.nameSuffix, "-") {
		// If the last segment is a number, it's considered invalid.
		// The backend automatically appends its own numeric suffix when chunking large state files into multiple secrets.
		// Allowing a user-defined numeric suffix could cause conflicts with this mechanism.
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("secret_suffix must not end with '-<number>', got %q", b.nameSuffix),
		)
	}

	b.config = cfg

	return nil
}

func getInitialConfig(data backendbase.SDKLikeData) (*restclient.Config, error) {
	var cfg *restclient.Config
	var err error

	inCluster := data.Bool("in_cluster_config")
	if inCluster {
		cfg, err = restclient.InClusterConfig()
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to d32a084675)