hashicorp/terraform · error
must be a valid ACL value , expected , or , got
Error message
%q must be a valid ACL value , expected %s, %s or %s, got %q
What it means
Thrown by the ValidateFunc for the 'acl' field in the OSS backend when the provided ACL string is not one of the three valid values: oss.ACLPrivate, oss.ACLPublicRead, or oss.ACLPublicReadWrite. The error interpolates the valid values and the invalid value received.
Solutions
- Use one of the exact constant string values: oss.ACLPrivate, oss.ACLPublicRead, or oss.ACLPublicReadWrite.
- Leave the acl field empty (default is empty string, which skips the check) if you want bucket-default ACL.
- Check the aliyun-oss-go-sdk source or docs for the exact string values of these constants.
Example fix
// before (invalid ACL name)
terraform {
backend "oss" {
acl = "authenticated-read"
}
}
// after
terraform {
backend "oss" {
acl = "private"
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate OSS ACL value before Terraform init
func validateOSSACL(acl string) error {
if acl == "" {
return nil // empty is allowed, uses bucket default
}
validACLs := map[string]bool{
"private": true,
"public-read": true,
"public-read-write": true,
}
if !validACLs[acl] {
return fmt.Errorf("invalid ACL %q; must be one of: private, public-read, public-read-write", acl)
}
return nil
} Prevention
- Use lowercase ACL values exactly as defined by OSS: 'private', 'public-read', 'public-read-write'.
- Leave the acl field empty to inherit the bucket's default ACL.
- Do not use AWS S3 ACL names like 'authenticated-read' or 'bucket-owner-read'.
When it happens
Trigger: ValidateFunc checks if value is non-empty, casts to oss.ACLType, and compares against the three valid constants. Fails when the user provides an unrecognized string like 'public', 'read-only', 'bucket-owner-read', or an AWS-style ACL like 'bucket-owner-full-control'.
Common situations: Developer uses an AWS S3 ACL name ('public-read-write' with different casing, or 'authenticated-read'). Developer uses a vague value like 'public' instead of 'public-read'. Copy-paste from S3 backend where ACL vocabulary differs. Case sensitivity issues ('Private' vs 'private').
Related errors
- describe oss endpoint using region: %#v got an error: %#v
- Error checking configuration
- Error creating workspace
- error getting object: %#v
- estimating object is exist got an error: %#v
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/71f373a0e037482a.
Report an issue: GitHub.
Appendix: 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 d32a084675)