hashicorp/terraform · error

%q must be a valid ACL value , expected %s, %s or %s, got %q

Error message

%q must be a valid ACL value , expected %s, %s or %s, got %q

What it means

Returned by the ValidateFunc of the acl attribute when the provided string is non-empty and is not one of the three supported OSS canned ACLs: private, public-read, public-read-write (oss.ACLPrivate / ACLPublicRead / ACLPublicReadWrite). It is a config-time guard before the OSS client ever applies the ACL.

Source

Thrown at internal/backend/remote-state/oss/backend.go:209

			},

			"encrypt": {
				Type:        schema.TypeBool,
				Optional:    true,
				Description: "Whether to enable server side encryption of the state file",
				Default:     false,
			},

			"acl": {
				Type:        schema.TypeString,
				Optional:    true,
				Description: "Object ACL to be applied to the state file",
				Default:     "",
				ValidateFunc: func(v interface{}, k string) ([]string, []error) {
					if value := v.(string); value != "" {
						acls := oss.ACLType(value)
						if acls != oss.ACLPrivate && acls != oss.ACLPublicRead && acls != oss.ACLPublicReadWrite {
							return nil, []error{fmt.Errorf(
								"%q must be a valid ACL value , expected %s, %s or %s, got %q",
								k, oss.ACLPrivate, oss.ACLPublicRead, oss.ACLPublicReadWrite, acls)}
						}
					}
					return nil, nil
				},
			},
			"shared_credentials_file": {
				Type:        schema.TypeString,
				Optional:    true,
				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ALICLOUD_SHARED_CREDENTIALS_FILE", "ALIBABA_CLOUD_CREDENTIALS_FILE"}, ""),
				Description: "This is the path to the shared credentials file. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used.",
			},
			"profile": {
				Type:        schema.TypeString,
				Optional:    true,
				Description: "This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable.",
				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"ALICLOUD_PROFILE", "ALIBABA_CLOUD_PROFILE"}, ""),

View on GitHub (pinned to c9def3e214)

Solutions

  1. Use exactly one of: private, public-read, public-read-write (hyphenated lowercase).
  2. If you do not need a custom ACL, omit the attribute entirely (default is empty = inherit bucket ACL).
  3. Double-check for underscores or camelCase typos.

Example fix

# before
acl = "public_read"

# after
acl = "public-read"
Defensive patterns

Strategy: type-guard

Type guard

var validOSSACLs = map[string]bool{
    "private": true, "public-read": true, "public-read-write": true,
}
func isValidOSSACL(a string) bool { return validOSSACLs[a] }

Prevention

When it happens

Trigger: Setting acl = "public" or acl = "bucket-owner-read" (an S3-style value) or any typo in the oss backend block. The ValidateFunc compares against the three OSS ACL constants.

Common situations: Migrating from the AWS S3 backend and reusing an S3 canned ACL string; typos like "public_read" (underscore) or "publicRead" (camelCase); setting a custom ACL that OSS does not support.

Related errors


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