{"record":{"id":"dfa7235c17acf490","repo":"kubernetes/kops","slug":"error-checking-gcs-bucket-acl-for-gs-s-for-s","errorCode":null,"errorMessage":"error checking GCS bucket ACL for gs://%s for %s: %v","messagePattern":"error checking GCS bucket ACL for gs://(.+?) for (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gcetasks/storagebucketacl.go","lineNumber":60,"sourceCode":"var _ fi.CompareWithID = (*StorageBucketAcl)(nil)\n\nfunc (e *StorageBucketAcl) CompareWithID() *string {\n\treturn e.Name\n}\n\nfunc (e *StorageBucketAcl) Find(c *fi.CloudupContext) (*StorageBucketAcl, error) {\n\tcloud := c.T.Cloud.(gce.GCECloud)\n\n\tbucket := fi.ValueOf(e.Bucket)\n\tentity := fi.ValueOf(e.Entity)\n\n\tklog.V(2).Infof(\"Checking GCS bucket ACL for gs://%s for %s\", bucket, entity)\n\trules, err := cloud.Storage().Bucket(bucket).ACL().List(context.TODO())\n\tif err != nil {\n\t\tif gce.IsNotFound(err) {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"error checking GCS bucket ACL for gs://%s for %s: %v\", bucket, entity, err)\n\t}\n\n\tfor _, r := range rules {\n\t\tif string(r.Entity) != entity {\n\t\t\tcontinue\n\t\t}\n\n\t\tfoundEntity := string(r.Entity)\n\t\tfoundRole := string(r.Role)\n\n\t\tactual := &StorageBucketAcl{}\n\t\tactual.Name = e.Name\n\t\tactual.Bucket = e.Bucket\n\t\tactual.Entity = &foundEntity\n\n\t\tactual.Role = &foundRole\n\n\t\t// Ignore \"system\" fields","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gcetasks/storagebucketacl.go#L42-L78","documentation":"StorageBucketAcl.Find wraps a failed cloud.google.com/go/storage Bucket ACL List call. kOps lists the bucket's ACL rules to compare desired vs actual state; any error other than NotFound (which is treated as \"no ACL yet\") is wrapped with the bucket and entity for context.","triggerScenarios":"cloud.Storage().Bucket(bucket).ACL().List(ctx) returns a non-nil, non-NotFound error during the Find phase of `kops update cluster`.","commonSituations":"The bucket is owned by another project and the kOps credentials lack storage.buckets.get; the bucket name refers to a bucket that doesn't exist (in a way not surfaced as NotFound, e.g. permission-masked 403); request failed due to network/proxy issues; storage.buckets.get denied by org policy on a cross-project bucket.","solutions":["Read the wrapped %v error: 403 => grant the caller storage.buckets.get / roles/storage.admin on the bucket's project; 404 => the bucket name is wrong or the bucket was deleted.","Confirm the bucket exists and is in the project kOps authenticates to: `gcloud storage buckets describe gs://<bucket>`.","If the bucket belongs to a different project, grant cross-project access or point the spec at the right bucket.","Retry after transient network/5xx errors."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"cmd := exec.Command(\"gcloud\", \"storage\", \"buckets\", \"describe\", \"gs://\"+bucket, \"--format=value(name)\")\nif err := cmd.Run(); err != nil {\n    return fmt.Errorf(\"bucket %q inaccessible with current credentials: %w\", bucket, err)\n}","typeGuard":null,"tryCatchPattern":"if err := kopsUpdate(); err != nil {\n    if strings.Contains(err.Error(), \"error checking GCS bucket ACL\") {\n        if strings.Contains(err.Error(), \"403\") {\n            log.Print(\"grant storage.buckets.get on the bucket's project\")\n        } else if isTransient(err) {\n            retryWithBackoff()\n        }\n    }\n    return err\n}","preventionTips":["Grant the kOps identity roles/storage.admin (or at least storage.buckets.get) on the bucket's project.","Confirm the bucket exists before the first apply (`gcloud storage buckets describe`).","Keep bucket tasks and ACL tasks in the same project/account.","Retry CI jobs once on transient network/5xx errors."],"tags":["gcs","gcp","storage","acl","api-error"],"backgroundTag":"gcs-bucket-api-error","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}