How to Debug GCP Cloud Functions Failures: Deploy Errors, Runtime Errors, Triggers, and Gen2 Logs

Cloud Functions fails in three distinct ways: the deploy never completes, the function deploys but crashes when invoked, or the function is healthy but never triggers. Each failure type has different logs, different root causes, and a different fix. This guide walks through all three with exact commands, log queries, and the gen1/gen2 differences that trip up most beginners.

Simple explanation

Every Cloud Functions problem falls into one of three buckets:

  • Deployment failed. Your function was never created. The source code did not build, a dependency was missing, or the entrypoint was wrong. The function does not exist in a runnable state.

  • Runtime failed. The function deployed and exists, but it crashes, returns errors, or times out when something invokes it. The build succeeded; the code breaks at execution time.

  • Trigger issue. The function is deployed and healthy, but it never runs. The event source (Pub/Sub, Cloud Storage, Eventarc) is not wired to the function correctly, so invocations never happen.

Analogy

Think of it like ordering takeout. A deployment failure means the restaurant closed before your meal was made. The food never existed. A runtime failure means the food was made but it came out wrong or spoiled. A trigger issue means the food is ready and sitting on the counter, but the delivery driver has the wrong address so it never reaches you.

Identifying which bucket you are in is the first step. Everything else follows from there.

Quick triage: what to check first

Start with the symptom you see and follow it to the right section of this guide.

SymptomLikely causeWhere to look
gcloud functions deploy failsBuild error: bad dependency, syntax error, wrong entrypointCloud Build logs
Function deploys but returns 500Runtime exception in your handler codeLogs Explorer filtered to the function
Function never triggersBroken Eventarc trigger, wrong Pub/Sub subscription, missing IAM on the triggerEventarc triggers list, Pub/Sub subscriptions
Gen2 function shows “no logs”Filtering on the wrong resource typeUse resource.type=“cloud_run_revision” instead of cloud_function
Function times outSlow downstream call, cold start, unoptimized DB queryLogs Explorer + Cloud Trace for latency breakdown
Permission denied at runtimeFunction’s service account lacks required IAM rolePermission Denied Errors guide
No logs at all (gen1 or gen2)Log exclusion filter, log sink misconfiguration, or the function never ranLogging exclusions page in console, Cloud Monitoring execution_count metric

How it works: the deployment and execution path

Understanding where failures can happen requires knowing the path your code takes from source to running function. For a deeper look at Cloud Functions architecture, see the Cloud Functions Overview.

Deployment path

  1. Source upload. You run gcloud functions deploy and GCP uploads your source directory to Cloud Storage.

  2. Build phase. Cloud Build installs dependencies, compiles if needed, and packages your code into a container image. Build failures stop here.

  3. Container registry. The built image is pushed to Artifact Registry (gen2) or Container Registry (gen1).

  4. Function creation. GCP creates the function resource pointing at the image. If the entrypoint does not match an exported function, this step fails.

Runtime path

  1. Trigger fires. An HTTP request, Pub/Sub message, Cloud Storage event, or Eventarc event targets the function.

  2. Instance startup. If no warm instance exists, GCP starts a new container instance (cold start). Global-scope code runs during this phase.

  3. Handler execution. Your function handler runs. Exceptions, timeouts, and permission errors happen here.

  4. Logging. All stdout and stderr go to Cloud Logging automatically. Gen1 logs to resource.type=“cloud_function”. Gen2 logs to resource.type=“cloud_run_revision” because gen2 runs on Cloud Run infrastructure.

Note

Gen2 Cloud Functions run on Cloud Run under the hood. This means gen2 deployment failures, runtime logs, and scaling behavior all follow Cloud Run patterns. If you are debugging a gen2 function and something looks unfamiliar, the Cloud Run Container Failed to Start guide often applies.

When to use this guide

Use this page when:

  • gcloud functions deploy exits with an error and you cannot tell why
  • Your function is deployed but invocations return 500, timeout, or crash
  • An event-driven function never fires even though events are happening
  • You migrated from gen1 to gen2 and your logs disappeared
  • You see “permission denied” errors at runtime but your function deployed fine
  • You need to figure out whether the problem is the function, the trigger, or the infrastructure

If you are choosing between Cloud Functions and Cloud Run for a new project, see Cloud Run vs Cloud Functions instead.

Deployment failures: the function was never created

Cloud Functions builds a container from your source code during deployment. If the build fails, the function is never created and gcloud functions deploy returns an error. The build logs are in Cloud Build, not Cloud Logging.

# Check the status of your function
gcloud functions list --format="table(name,status,updateTime)"

# Get the Cloud Build log URL from a failed deployment
gcloud functions describe FUNCTION_NAME \
  --region=REGION \
  --format="value(buildConfig.build)"

# Read build logs directly
gcloud logging read \
  'resource.type="build" AND resource.labels.build_id=BUILD_ID' \
  --limit=100 \
  --format="value(textPayload)"

Missing dependencies

Every runtime requires a dependency file. Node.js needs package.json with all dependencies listed. Python needs requirements.txt. Go needs go.mod. If any package cannot install (version conflict, typo, private registry), the build fails.

# Test locally before deploying (Node.js example)
rm -rf node_modules && npm install

# Python example
pip install -r requirements.txt --dry-run

Wrong entrypoint

The —entry-point flag must match an exported function name in your source code exactly. A mismatch causes the deployment to fail after the build succeeds. This is case-sensitive.

# Deploy with an explicit entrypoint
gcloud functions deploy my-function \
  --entry-point=handleRequest \
  --runtime=nodejs20 \
  --trigger-http \
  --region=us-central1

Syntax and build errors

Syntax errors in your code cause the build to fail before invocation is possible. The build log shows the exact file and line number. Check the Cloud Build log output first. It usually points directly to the problem.

Build service account permissions

Gen2 functions use Cloud Build with a service account that needs permission to write to Artifact Registry and access your source. If you see “permission denied” during the build phase (not at runtime), the build service account is missing a required role. This is separate from the function’s runtime service account.

Tip

Cloud Build logs are the single source of truth for deployment failures. Do not look in Cloud Logging under the function resource. Those logs only exist after the function deploys successfully.

Runtime failures: the function crashes when invoked

Runtime failures happen after a successful deployment. The function exists and can receive invocations, but it throws exceptions, returns errors, or crashes. Cloud Functions captures all stdout and stderr and sends it to Cloud Logging automatically.

# Read logs for a gen1 Cloud Function
gcloud logging read \
  'resource.type="cloud_function" AND resource.labels.function_name="my-function"' \
  --project=PROJECT_ID \
  --limit=50 \
  --order=desc \
  --format="table(timestamp, severity, textPayload, jsonPayload.message)"

# Filter for errors only
gcloud logging read \
  'resource.type="cloud_function" AND resource.labels.function_name="my-function" AND severity>=ERROR' \
  --project=PROJECT_ID \
  --limit=20

# For gen2 functions (logs appear under cloud_run_revision)
gcloud logging read \
  'resource.type="cloud_run_revision" AND resource.labels.service_name="my-function"' \
  --project=PROJECT_ID \
  --limit=50

Each invocation produces log entries starting with “Function execution started” and ending with “Function execution took X ms, finished with status: X”. A status of error means the function threw an exception or returned a non-2xx response. The exception and stack trace appear between the start and end entries.

What to look for in runtime logs

  • Unhandled exceptions. The stack trace appears in the logs. Read it from the bottom up to find the root cause.

  • 500 responses on HTTP functions. If your function does not explicitly set a status code and an error occurs, Cloud Functions returns 500. Check for uncaught exceptions in the handler.

  • Crash loops. If the function crashes on every invocation, you will see repeated “started” / “error” pairs in the logs. This usually means a missing environment variable, a broken dependency at runtime, or a database connection that fails immediately.

For deeper runtime analysis, open the Logs Explorer in the GCP Console. It lets you filter, search, and correlate log entries across time ranges much faster than the CLI.

Timeout errors

A function that exceeds its timeout is terminated and the invocation is recorded as an error. The log entry says “Function execution took X ms, finished with status: timeout.”

Gen1 functions: default 60 seconds, maximum 540 seconds (9 minutes). Gen2 functions: default 60 seconds, maximum 3600 seconds (60 minutes).

# Increase timeout for a gen1 function
gcloud functions deploy my-function \
  --timeout=300s \
  --region=REGION

# Increase timeout for a gen2 function
gcloud functions deploy my-function \
  --gen2 \
  --timeout=600s \
  --region=REGION
Tip

Before increasing the timeout, investigate why the function is slow. Blindly raising the limit masks the real problem. Common root causes:

  • N+1 database queries. The function queries a database once per item in a loop instead of batching. This is the most common cause of slow Cloud Functions.

  • Synchronous HTTP calls to slow services. If your function calls an external API that takes 10 seconds to respond, the function waits 10 seconds.

  • Loading large files on every invocation. Move large-file loads to global scope so they persist across warm invocations instead of re-loading every time.

  • Cold start + slow initialization. Database connections, SDK clients, or configuration loads that happen during cold start can push total execution past the limit. Use Cloud Trace to see where time is spent within a single invocation.

  • VPC connector latency. Functions using Serverless VPC Access to reach private resources add network overhead. Make sure the connector is in the same region as the function and the target resource.

Permission failures at runtime

Cloud Functions does not run as your personal GCP account. It runs as a service account. If that service account lacks a required IAM role, the function gets a permission denied error when it calls another GCP service (Cloud Storage, BigQuery, Pub/Sub, Secret Manager).

Default service accounts

Warning

Both default service accounts have broad permissions in new projects. In production, teams typically restrict or replace them with least-privilege custom service accounts. If your function worked in a test project but fails in production, the most likely cause is a restricted default service account. Always deploy with a dedicated service account that has only the roles the function needs.

Check which service account your function actually uses:

# Check what service account a deployed function uses
gcloud functions describe my-function \
  --region=REGION \
  --format="value(serviceConfig.serviceAccountEmail)"

# Deploy with a dedicated service account
gcloud functions deploy my-function \
  --service-account=my-function-sa@my-project.iam.gserviceaccount.com \
  --region=REGION

# List the roles granted to that service account on the project
gcloud projects get-iam-policy PROJECT_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:my-function-sa@my-project.iam.gserviceaccount.com" \
  --format="table(bindings.role)"

For a full walkthrough of diagnosing IAM errors, see GCP Permission Denied Errors. If your function reads secrets, make sure the service account has roles/secretmanager.secretAccessor on the specific secret. See Secret Manager Overview for setup details.

Event trigger failures: function never executes

Functions triggered by Pub/Sub, Cloud Storage events, or Eventarc can deploy successfully but never execute when the event fires. The function is healthy, but the trigger wiring is broken. This is a different problem from a runtime crash.

How to tell: trigger broken vs function crashing

Check the Cloud Monitoring metric cloudfunctions.googleapis.com/function/execution_count for your function:

  • Execution count stays at zero when events are firing → the trigger is misconfigured. The function is never being invoked.

  • Execution count increments but error count also rises → the trigger works, but the function crashes when it runs. Look at runtime logs instead.

Diagnosing trigger issues

# List Eventarc triggers for gen2 functions
gcloud eventarc triggers list --location=REGION

# Describe a specific trigger to check its configuration
gcloud eventarc triggers describe TRIGGER_NAME --location=REGION

# For Pub/Sub triggers, check the subscription exists and is active
gcloud pubsub subscriptions list --filter="topic:my-topic"

# Test a Pub/Sub trigger by publishing a message directly
gcloud pubsub topics publish my-topic \
  --message='{"test": "message"}'

Common trigger failures:

  • Eventarc trigger points to the wrong function or region. Verify the trigger’s destination matches the function name and region exactly.

  • Pub/Sub subscription was deleted or recreated. If you delete and redeploy a function, the subscription may not reconnect automatically. Check that the subscription push endpoint matches the function URL.

  • Missing IAM on the trigger service account. Eventarc triggers need the Eventarc Event Receiver role on the function. Pub/Sub push subscriptions need permission to invoke the function.

  • Event format mismatch. Gen1 event functions expect a specific event envelope. Gen2 uses CloudEvents. If you migrated your trigger setup without updating the function signature, events arrive but the function cannot parse them.

Gen1 to gen2 migration trap

If you migrate a gen1 event-triggered function to gen2 without changing the function signature, the function may deploy successfully but silently fail on every invocation. Gen1 passes the event directly as a function argument. Gen2 wraps it in a CloudEvent envelope. Your function receives the wrapper instead of the data, parses nothing, and returns without error. Check your function signature matches the gen2 CloudEvents format.

For Pub/Sub-specific delivery problems (backlogs, dead letters, ack deadline issues), see Pub/Sub Message Delivery Failures.

Cold start and startup crashes

A cold start happens when Cloud Functions starts a new instance. The runtime initializes, imports packages, sets global variables, and runs any top-level code before the handler is invoked. Cold start crashes reveal bugs in initialization code that warm invocations hide.

Analogy

A cold start is like opening a restaurant in the morning. Before serving the first customer, you turn on the lights, heat the ovens, prep the ingredients, and check the inventory. If any of that fails (the oven is broken, a delivery did not arrive), the first customer waits or gets turned away. But once the kitchen is running, the next customers are served fast. The same applies to Cloud Functions: global-scope code runs once during startup, and if it breaks, only the first invocation sees the crash.

Check for these patterns in global scope:

  • Network calls at import time. An HTTP request or database connection attempt that runs when the module loads can time out on first invocation, especially if the target service is slow to respond.

  • Secret Manager reads in global scope. If you fetch secrets outside the handler and the function’s service account does not have access, the function crashes before it ever reaches your handler code.

  • File reads that work locally but fail in Cloud Functions. Only files in the deployment package are available. If your code reads a config file at ./config/settings.json that was in .gcloudignore, it is not deployed.

  • Large dependency initialization. Heavy packages (ML models, large SDKs) can push cold start time past the timeout. If your function needs large initialization, consider using gen2 for its higher timeout limits or moving to Cloud Run for more control over startup.

Move risky operations (network calls, file reads, secret fetches) inside the handler function or wrap them in try/except with a fallback. Keep global-scope initialization limited to database client creation and SDK setup, where failures are immediate and diagnosable.

Note

Gen2 cold start crashes may look like Cloud Run startup failures. If your gen2 function fails during initialization, check the Cloud Run Container Failed to Start guide as well. The same troubleshooting steps apply.

Gen1 vs gen2 debugging differences

Gen1 and gen2 Cloud Functions behave differently under the hood, which changes where you look when things break. This table covers the key differences for debugging:

AspectGen1Gen2
Runtime logs locationresource.type=“cloud_function”resource.type=“cloud_run_revision”
Trigger modelBuilt-in triggers (HTTP, Pub/Sub, GCS, Firestore)Eventarc for event triggers, HTTP for direct calls
Underlying infrastructureCustom Cloud Functions runtimeCloud Run
Default service accountApp Engine default SACompute Engine default SA
Max timeout540 seconds3600 seconds
Build systemCloud Build (implicit)Cloud Build (explicit, visible in console)
Common confusionLogs are where you expect them”No logs” because you filtered on the wrong resource type
What to check firstCloud Logging with cloud_function filterCloud Logging with cloud_run_revision filter, then Eventarc triggers
Warning

The single most common gen2 debugging mistake is filtering Cloud Logging on resource.type=“cloud_function” and seeing nothing. Gen2 runs on Cloud Run, so all runtime logs appear under resource.type=“cloud_run_revision”. Switch the filter and your logs appear immediately. If you only remember one thing from this table, remember the resource type change.

Common mistakes

  1. Looking for gen2 logs under resource.type=“cloud_function”. Gen2 function logs appear under resource.type=“cloud_run_revision”. If you see no logs for a gen2 function, switch the resource type filter.

  2. Assuming the function runs with your personal account permissions. Cloud Functions runs as a service account, not your user account. Your personal IAM permissions have no effect on what the function can do at runtime. Always check which service account is attached.

  3. Increasing timeout without investigating root cause. A timeout error means the function is slow, not that the limit is wrong. Raising the timeout from 60s to 300s does not fix a function that makes 50 sequential HTTP calls.

  4. Not including all required files in the deployment. Only files in the source directory (minus .gcloudignore exclusions) are deployed. If the function reads a local config file that was excluded, it fails with “file not found.”

  5. Checking the console function summary instead of Logs Explorer. The function detail page shows a high-level status. The full error message, exception, and stack trace are only in Logs Explorer.

  6. Confusing a broken trigger with a broken function. If execution_count is zero, the function never ran. The problem is the trigger, not the function code. Check Eventarc or Pub/Sub configuration before debugging the function itself.

  7. Using smart quotes or em-dashes in CLI commands. Copy-pasting from formatted docs or chat can introduce —entry-point as —entry-point. Always type flags manually or paste from a plain-text source.

Cloud Functions vs Cloud Run troubleshooting

Since gen2 Cloud Functions run on Cloud Run, the debugging boundary between the two can be confusing. Here is how to think about it:

  • Debug the function when the problem is in your code: wrong logic, unhandled exceptions, bad event parsing, missing environment variables.

  • Debug Cloud Run when the problem is infrastructure: container startup failures, port binding issues, resource limits, concurrency settings, scaling to zero and back. These affect gen2 functions because they run as Cloud Run services.

If your gen2 function fails with errors you do not recognize from Cloud Functions docs, check the Cloud Run Container Failed to Start guide. For a broader comparison of the two services, see Cloud Run vs Cloud Functions.

For understanding how event-driven patterns work in Cloud Functions and how triggers connect to your code, that context helps distinguish “my event handling code is wrong” from “events are not reaching my function.”

Frequently asked questions

My Cloud Function deploys successfully but returns 500 errors at runtime. Where do I look first?

Open Cloud Logging and filter to your function name. Gen1 functions log under resource.type="cloud_function" with resource.labels.function_name matching your function. Gen2 functions log under resource.type="cloud_run_revision" with resource.labels.service_name matching your function. Look for the entries between "Function execution started" and "Function execution took X ms, finished with status: error". The exception and stack trace appear there.

What is the difference between a deployment error and a runtime error in Cloud Functions?

A deployment error happens during the build phase: missing packages, build failures, or an entrypoint that does not match an exported function. Deployment errors appear in Cloud Build logs and gcloud functions deploy returns a non-zero exit code. A runtime error happens after the function deploys successfully, when it is invoked and crashes. Runtime errors appear in Cloud Logging under the function resource type.

How do I find Cloud Functions gen2 logs? They do not appear under resource.type cloud_function.

Gen2 Cloud Functions run on Cloud Run infrastructure, so their logs appear under resource.type="cloud_run_revision" in Cloud Logging. Filter on resource.labels.service_name matching your function name. This catches most people migrating from gen1 to gen2 because the resource type changes even though you are still using Cloud Functions.

Why does my Cloud Function work in the console test but fail when triggered by Pub/Sub?

The console test sends a simplified synthetic event. A real Pub/Sub trigger delivers a push message with base64-encoded data in a specific envelope format. Make sure your function decodes the data correctly: event.data in gen1, or the CloudEvent data field in gen2. Also verify the Pub/Sub subscription actually targets your function by checking gcloud eventarc triggers list or the Pub/Sub subscription push endpoint.

How do I tell if my Cloud Function trigger is broken vs the function itself is crashing?

Check the Cloud Monitoring metric cloudfunctions.googleapis.com/function/execution_count for your function. If the count stays at zero when events should be firing, the trigger is misconfigured and the function is never being invoked. If the count increments but the error_count metric also rises, the trigger works but the function crashes when it runs. For gen2, also check eventarc audit logs to confirm events are being routed.

Last verified: 27 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.