kubernetes/kops · error
unknown writeable path, can't apply IAM policy: %q
Error message
unknown writeable path, can't apply IAM policy: %q
What it means
In the writeable-path half of AddS3Permissions, kOps grants S3 write statements only for S3Path, MemFSPath and FSPath types returned by WriteableVFSPaths. If an etcd backupStore (or other writeable path) resolves to any other vfs.Path implementation, the builder cannot emit matching IAM statements and returns this error with the path quoted.
Source
Thrown at pkg/model/iam/iam_builder.go:652
for _, vfsPath := range writeablePaths {
switch path := vfsPath.(type) {
case *vfs.S3Path:
iamS3Path := path.Bucket() + "/" + path.Key()
iamS3Path = strings.TrimSuffix(iamS3Path, "/")
b.buildS3WriteStatements(p, iamS3Path)
s3Buckets.Insert(path.Bucket())
case *vfs.MemFSPath:
iamS3Path := "placeholder-write-bucket/" + path.Location()
b.buildS3WriteStatements(p, iamS3Path)
s3Buckets.Insert("placeholder-write-bucket")
case *vfs.FSPath:
iamS3path := "placeholder-read-bucket/" + strings.TrimPrefix(path.Path(), "file://")
b.buildS3WriteStatements(p, iamS3path)
s3Buckets.Insert("placeholder-read-bucket")
default:
return fmt.Errorf("unknown writeable path, can't apply IAM policy: %q", vfsPath)
}
}
// We need some permissions on the buckets themselves
for _, s3Bucket := range s3Buckets.List() {
p.Statement = append(p.Statement, &Statement{
Effect: StatementEffectAllow,
Action: stringorset.Of(
"s3:GetBucketLocation",
"s3:GetEncryptionConfiguration",
"s3:ListBucket",
"s3:ListBucketVersions",
),
Resource: stringorset.Set([]string{
fmt.Sprintf("arn:%v:s3:::%v", p.partition, s3Bucket),
}),
})
}View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the quoted path in the error to find which backupStore is offending.
- Change every etcdClusters backupStore to a valid s3:// URL in the AWS cluster spec via `kops edit cluster`.
- If the backup store scheme is intentionally non-S3, AWS IAM policies cannot cover it — use S3 for backups on AWS clusters.
- After fixing, rerun `kops update cluster` to regenerate the master IAM policy.
Example fix
// before backups: backupStore: "azure://backups/example.k8s.local" // after backups: backupStore: "s3://my-kops-bucket/backups/example.k8s.local"
Defensive patterns
Strategy: validation
Validate before calling
vp, err := vfs.Context.BuildVfsPath(backupStore)
if err != nil { return err }
switch vp.(type) {
case *vfs.S3Path, *vfs.MemFSPath, *vfs.FSPath:
// supported for IAM write statements
default:
return fmt.Errorf("unsupported writeable backup store %q", backupStore)
} Try / catch
if err := builder.AddS3Permissions(policy); err != nil {
if strings.Contains(err.Error(), "unknown writeable path") {
// fix etcd backupStore in cluster spec
}
return err
} Prevention
- Keep etcd backupStore on s3:// for AWS clusters
- Grep the cluster spec for non-s3 backupStore values before update
- Validate with `kops get cluster -o yaml | grep backupStore`
When it happens
Trigger: NodeRoleMaster policy build where cluster.Spec.EtcdClusters[*].Backups.BackupStore parses (BuildVfsPath succeeded) into a vfs.Path that is not S3/MemFS/FS — e.g. a GCS or Azure backup store URL used with AWS master role IAM generation.
Common situations: etcd-manager backupStore copied from a GCE/Azure cluster into an AWS cluster spec; custom or future VFS backend for backups; hand-edited cluster spec with a typo'd scheme that still resolves via an unexpected path type.
Related errors
- failed to generate AWS IAM S3 access statements: %v
- failed to generate AWS IAM Policy: %v
- cannot parse VFS path %q: %v
- path is not cluster readable: %v
- error building IAM policy: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/5df4a21688a67ed9.
Report an issue: GitHub.