GCP ACE common mistakes
GCP ACE · Understand the traps and how to avoid them.
Sets the target project once with `gcloud config set project` and then runs every later command without `--project`, including commands issued from another terminal, script, or CI step.
gcloud config is per-configuration and per-shell environment (CLOUD_SDK_CONFIG_DIR). A second terminal, an activated configuration, or a wrapper script silently targets a different project, and exam scenarios often describe multi-project layouts where this exact drift is the point of the question.
What to do instead
Pass --project explicitly on each command, or create and activate named configurations (gcloud config configurations create/activate), and confirm the active context with gcloud config list before acting on any resource.
Assumes a newly created project can immediately create resources, and never checks API enablement, billing linkage, or org policy constraints before diagnosing a failure as an IAM problem.
Labs and tutorials begin from an already-configured project, so the setup steps are invisible. On the exam the symptom is usually PERMISSION_DENIED or SERVICE_DISABLED, which look like missing roles but are actually unenabled services, an unlinked billing account, or a constraint such as restricting external IPs.
What to do instead
Treat gcloud services enable, billing linkage, and org policy constraints as distinct setup steps, and make them the first thing to verify whenever a resource creation fails, before touching IAM bindings.
Chooses a location flag without first classifying the resource as zonal, regional, or global - for example passing `--zone` when creating a regional GKE control plane, or expecting a Cloud Storage bucket or a global load balancer address to be regional.
Scope is hidden behind console defaults and the flag names differ per product (zone, region, location, multi-region) while sounding interchangeable, so candidates pattern-match on the word 'location' instead of on the resource type.
What to do instead
Memorize scope per resource: Compute instances, persistent disks and GKE nodes are zonal; subnets, Cloud SQL instances and the GKE control plane are regional; buckets, container images, global load balancers, service accounts and IAM policy are global. Let the flag name in the question be the hint.
Designs the network assuming the default VPC, its auto-mode subnets, and its permissive firewall rules exist in every region, and assumes VPC firewall rules also gate traffic to Cloud SQL, App Engine, or to Google's load balancer health checkers.
Hands-on practice usually happens in a project with the default network, which hides the need for custom-mode subnets and explicit ingress rules. Firewall rules attach to VM network interfaces only, and health check probes originate from Google-owned ranges rather than from the VPC.
What to do instead
In custom mode, create one subnet per region, write ingress rules scoped by target tags or service accounts, and allow 35.191.0.0/16 and 130.211.0.0/22 for health checks. Remember Cloud SQL reachability is controlled by authorized networks or private IP, not by VPC firewall rules.
Pushes or pulls container images without first running `gcloud auth configure-docker` for the correct registry host in the same environment, or mixes hostnames - using `gcr.io/<project>/...` when the image lives in Artifact Registry's `<location>-docker.pkg.dev/<project>/<repo>/...`.
Container Registry and Artifact Registry are separate services with different hostnames, IAM models, and credential helpers. A Docker daemon configured once for one host keeps working for that host, so the mismatch only surfaces when the registry or region changes.
What to do instead
Use the fully qualified Artifact Registry path <location>-docker.pkg.dev/<project>/<repo>/<image>, run gcloud auth configure-docker <location>-docker.pkg.dev on the machine that builds or pushes, and grant the runtime identity roles/artifactregistry.reader on the repository.
Deploys a containerized or source-based service and then treats the resulting 403 or build failure as a code bug - for example expecting an unauthenticated Cloud Run service by default, or assuming App Engine standard will build an arbitrary Dockerfile.
gcloud run deploy succeeds and requires authentication unless told otherwise, so the failure appears later at request time; App Engine standard supports a fixed set of runtimes while only the flexible environment consumes a Dockerfile, so the deploy fails at build time for a reason unrelated to the application.
What to do instead
Add --allow-unauthenticated for public Cloud Run services and call private ones with an identity token. Choose App Engine flexible or Cloud Run when a custom container is required, and standard only when the runtime is on the supported list.
Searches Cloud Logging for Data Access entries (for example a `storage.objects.get`) to prove who read an object, finds nothing, and concludes the read never happened or that logging is broken.
Admin Activity and System Event logs are always enabled, but Data Access logs are disabled by default for most services (BigQuery being the notable exception) and must be explicitly turned on, and they are billable - so the absence of a read entry is expected on a default project.
What to do instead
Know the four log types and their default states, enable Data Access logs explicitly at the project, folder, or org level before relying on them, and use Admin Activity logs to prove configuration changes rather than data reads.
Creates an alerting policy or uptime check and waits for a notification, or expects memory, disk, and process metrics from a Compute Engine instance without installing an agent.
An alerting policy with no notification channel attached fires silently, uptime checks need a reachable endpoint and a firewall path from the checker locations, and the platform-provided VM metrics cover CPU and network only - memory and disk require the Ops Agent.
What to do instead
Attach a notification channel to every alerting policy, confirm the uptime check's source ranges are allowed through the firewall, and install the Ops Agent whenever the scenario asks for memory, disk, or process-level metrics.
Grants a human `roles/editor` at project level and then expects them to deploy a VM, GKE node pool, or Cloud Function that runs as a custom service account.
Attaching a service account to a resource is an actAs operation requiring iam.serviceAccounts.actAs (contained in roles/iam.serviceAccountUser). Project-level edit does not imply it, and neither does holding a key for that service account, so the deploy fails with a permission error that looks unrelated to the role that was granted.
What to do instead
Grant roles/iam.serviceAccountUser on the service account (or at project level) to the deploying principal, and independently keep the runtime service account's own permissions scoped to what the workload actually calls.
Responds to a permission error by adding a broad primitive role at project level, or tries to remove an inherited grant by editing the project-level policy of the same principal.
IAM policies are additive and inherited down the resource hierarchy, so a grant made at the organization or folder cannot be revoked by a project-level change, and primitive roles such as editor include thousands of permissions that mask which one was actually required.
What to do instead
Identify the specific API permission being denied, select the least-privileged predefined or custom role, bind it at the highest resource in the hierarchy where it is needed, and remember that removing access means changing the binding at the level where it was granted.