kubernetes/kops · error
write to %s with ACL of unexpected type %T
Error message
write to %s with ACL of unexpected type %T
What it means
getRequestACL converts the vfs ACL option into an S3 request ACL. If the ACL passed via vfs ACL option is not *S3Acl (and not a plain canned-ACL string), the write is aborted with "write to <path> with ACL of unexpected type %T". This is a programming error: the caller supplied an ACL type meant for a different backend.
Source
Thrown at util/pkg/vfs/s3fs.go:311
sseLog = "AES256"
sse = types.ServerSideEncryptionAes256
}
}
return sse, sseLog, nil
}
func (p *S3Path) getRequestACL(aclObj ACL) (*types.ObjectCannedACL, error) {
acl := os.Getenv("KOPS_STATE_S3_ACL")
acl = strings.TrimSpace(acl)
if acl != "" {
cannedACL := types.ObjectCannedACL(acl)
klog.V(8).Infof("Using KOPS_STATE_S3_ACL=%s", acl)
return &cannedACL, nil
} else if aclObj != nil {
s3Acl, ok := aclObj.(*S3Acl)
if !ok {
return nil, fmt.Errorf("write to %s with ACL of unexpected type %T", p, aclObj)
}
return s3Acl.RequestACL, nil
}
return nil, nil
}
func (p *S3Path) WriteFile(ctx context.Context, data io.ReadSeeker, aclObj ACL) error {
ctx, span := tracer.Start(ctx, "S3Path::WriteFile", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
client, err := p.client(ctx)
if err != nil {
return err
}
klog.V(4).Infof("Writing file %q", p)
request := &s3.PutObjectInput{}View on GitHub (pinned to 4c8573c808)
Solutions
- Pass *vfs.S3Acl (constructed with the desired types.ObjectCannedACL) when writing to S3 paths
- Alternatively pass the canned ACL as a plain string (handled by the KOPS_STATE_S3_ACL string branch) or set the KOPS_STATE_S3_ACL env var and omit the option
- Audit generic write helpers to select the backend-specific ACL type based on the path type
Example fix
// before
err = vfs.Context.WriteFile(p, data, vfsopt.WithACL(gcutil.NewAcl("project-owner")))
// after
err = vfs.Context.WriteFile(p, data, vfsopt.WithACL(vfs.NewS3Acl("private"))) Defensive patterns
Strategy: validation
Validate before calling
switch acl := opt.(type) {
case *vfs.S3Acl:
// ok
case string:
// ok, canned ACL
default:
return fmt.Errorf("backend %T needs a backend-specific ACL, got %T", p, opt)
} Type guard
func isS3Acl(a any) bool { _, ok := a.(*vfs.S3Acl); return ok } Try / catch
if err := vfs.Context.WriteFile(p, data, opts...); err != nil {
if strings.Contains(err.Error(), "ACL of unexpected type") {
return rebuildOptionsForBackend(p, data)
}
return err
} Prevention
- Match ACL option type to the path backend (S3Acl for S3, GSAcl for GCS)
- Prefer KOPS_STATE_S3_ACL env var over code-supplied ACL structs
- Centralize ACL option construction in backend-aware helpers
When it happens
Trigger: Calling WriteFile (directly or via CreateFile) with an ACL option set to e.g. *GSAcl, *azure ACL type, or any non-*S3Acl object while writing to an S3 path.
Common situations: Generic tooling that applies the same vfs.ACL option across cloud backends; copy-pasted code passing a GCS ACL to an S3 state store; custom vfs wrappers constructing the wrong ACL struct.
Related errors
- unexpected path type %T for %q
- the %q path is intended for use in tests
- the %q path does not support public ACL
- write to %s with ACL of unexpected type %T
- error writing %s (with ACL=%q): %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/0b1a67a8831320bd.
Report an issue: GitHub.