hashicorp/terraform · warning

acl value invalid, expected %s or %s, got %s

Error message

acl value invalid, expected %s or %s, got %s

What it means

ValidateFunc for the cos backend's `acl` attribute (cos/backend.go:167). Only 'private' and 'public-read' are accepted; any other ACL string fails validation. State files contain secrets, so 'private' is the safe default.

Source

Thrown at internal/backend/remote-state/cos/backend.go:167

					}
					return nil, nil
				},
			},
			"encrypt": {
				Type:        schema.TypeBool,
				Optional:    true,
				Description: "Whether to enable server side encryption of the state file",
				Default:     true,
			},
			"acl": {
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Object ACL to be applied to the state file",
				Default:     "private",
				ValidateFunc: func(v interface{}, s string) ([]string, []error) {
					value := v.(string)
					if value != "private" && value != "public-read" {
						return nil, []error{fmt.Errorf(
							"acl value invalid, expected %s or %s, got %s",
							"private", "public-read", value)}
					}
					return nil, nil
				},
			},
			"accelerate": {
				Type:        schema.TypeBool,
				Optional:    true,
				Description: "Whether to enable global Acceleration",
				Default:     false,
			},
			"assume_role": {
				Type:        schema.TypeSet,
				Optional:    true,
				MaxItems:    1,
				Description: "The `assume_role` block. If provided, terraform will attempt to assume this role using the supplied credentials.",
				Elem: &schema.Resource{

View on GitHub (pinned to c9def3e214)

Solutions

  1. Set acl = "private" (the default and recommended value for state).
  2. Use acl = "public-read" only if you have a specific reason and understand state exposure.
  3. Do not use S3-only ACL names; COS supports a narrower set.

Example fix

// before
terraform {
  backend "cos" {
    acl = "public-read-write"
  }
}
// after
terraform {
  backend "cos" {
    acl = "private"
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the cos acl value before passing it to the backend
func validACL(v string) error {
    if v != "private" && v != "public-read" {
        return fmt.Errorf("acl must be 'private' or 'public-read', got %q", v)
    }
    return nil
}

Type guard

// isSupportedCosACL narrows a string to an allowed COS ACL
func isSupportedCosACL(v string) bool {
    return v == "private" || v == "public-read"
}

Prevention

When it happens

Trigger: Setting acl to anything other than 'private' or 'public-read' (e.g. 'public-read-write', 'bucket-owner-full-control') in the backend block.

Common situations: Carrying over an S3-style ACL value; assuming full AWS S3 ACL names are supported; accidentally exposing state with a public ACL.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/2c9a76d2b5c5507d. Report an issue: GitHub.