kubernetes/kops · error
error updating GCS bucket IAM for gs://%s: %v
Error message
error updating GCS bucket IAM for gs://%s: %v
What it means
StorageBucketIAM.RenderGCE wraps a failed IAM().V3().SetPolicy call. After patching the fetched policy with the desired member binding, kOps writes the whole policy back; a failure here means the binding was not applied to the bucket.
Source
Thrown at upup/pkg/fi/cloudup/gcetasks/storagebucketiam.go:126
member := "serviceAccount:" + fi.ValueOf(e.MemberServiceAccount.Email)
role := fi.ValueOf(e.Role)
klog.V(2).Infof("Creating GCS bucket IAM for gs://%s for %s as %s", bucket, member, role)
policy, err := t.Cloud.Storage().Bucket(bucket).IAM().V3().Policy(ctx)
if err != nil {
return fmt.Errorf("error creating IAM policy for bucket gs://%s: %w", bucket, err)
}
changed := patchPolicy(policy, member, role)
if !changed {
klog.Warningf("did not need to change policy (concurrent change?)")
return nil
}
if err := t.Cloud.Storage().Bucket(bucket).IAM().V3().SetPolicy(ctx, policy); err != nil {
return fmt.Errorf("error updating GCS bucket IAM for gs://%s: %v", bucket, err)
}
return nil
}
// terraformStorageBucketIAM is the model for a terraform google_storage_bucket_iam_member rule
type terraformStorageBucketIAM struct {
Bucket string `cty:"bucket"`
Role string `cty:"role"`
Member *terraformWriter.Literal `cty:"member"`
}
func (_ *StorageBucketIAM) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *StorageBucketIAM) error {
tf := &terraformStorageBucketIAM{
Bucket: fi.ValueOf(e.Bucket),
Role: fi.ValueOf(e.Role),
Member: e.MemberServiceAccount.TerraformLink_Member(),
}View on GitHub (pinned to 4c8573c808)
Solutions
- Read the wrapped error: 403 => grant roles/storage.admin / storage.buckets.setIamPolicy; 409/conflict => re-run update (policy is re-fetched each run).
- Check org policy constraints/iam.allowedPolicyMemberDomains if the member is outside allowed domains.
- Ensure the member service account actually exists (a deleted SA email can be rejected on write).
- Retry on transient 429/5xx; verify with `gcloud storage buckets get-iam-policy gs://<bucket>` after a successful run.
Defensive patterns
Strategy: retry
Validate before calling
if !hasPerm("storage.buckets.setIamPolicy") {
return fmt.Errorf("identity lacks storage.buckets.setIamPolicy on gs://%s", bucket)
}
if fi.ValueOf(e.MemberServiceAccount.Email) == "" {
return fmt.Errorf("member service account email must be set")
} Try / catch
if err := kopsUpdate(); err != nil {
if strings.Contains(err.Error(), "error updating GCS bucket IAM") {
if strings.Contains(err.Error(), "403") {
log.Print("grant storage.buckets.setIamPolicy")
} else if strings.Contains(err.Error(), "409") || isTransient(err) {
log.Print("policy changed concurrently or transient error; re-run update")
}
}
return err
} Prevention
- Grant storage.buckets.setIamPolicy (roles/storage.admin) to the kOps identity.
- Confirm the member service account exists before binding it to the policy.
- Re-run update on conflict errors — the policy is re-fetched each run.
- Verify the binding afterwards with `gcloud storage buckets get-iam-policy`.
When it happens
Trigger: SetPolicy(ctx, policy) returns an error after patchPolicy modified the bindings, during RenderGCE of a StorageBucketIAM task.
Common situations: kOps credentials lack storage.buckets.setIamPolicy; the policy changed concurrently and the write conflicts (retry will re-read); bucket deleted mid-apply; org policy domain-restricted-sharing rejects binding an out-of-domain service account member.
Related errors
- error checking GCS bucket IAM for gs://%s: %w
- error creating IAM policy for bucket gs://%s: %w
- error checking GCS bucket ACL for gs://%s for %s: %v
- error setting GCS bucket ACL for gs://%s for %s as %s: %v
- error creating ServiceAccount %q: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/e50808c49c9d7161.
Report an issue: GitHub.