If you've ever seen the error "VPC connector and direct VPC can not be used together" when deploying a Cloud Run service, you've hit one of GCP's most confusing networking gotchas. It took us 3 days of debugging to figure out what was happening.
This guide explains the two VPC networking modes on Cloud Run, why they conflict, and how to fix it.
The Two Networking Modes
Cloud Run services can connect to VPC resources (like Cloud SQL, Memorystore Redis, or private GKE clusters) in two ways:
Mode 1: VPC Connector (Serverless VPC Access)
A VPC Connector is a managed service that creates a bridge between your Cloud Run service and your VPC network. It's the recommended approach for most use cases.
# Deploy with VPC Connector
gcloud run deploy my-service \
--vpc-connector projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME \
--vpc-egress all-traffic
When to use:
- You need access to private IP resources (Cloud SQL private IP, Memorystore, private GKE)
- You want managed networking (Google handles scaling, HA)
- You're okay with a small latency overhead (~1-2ms)
Mode 2: Direct VPC Egress
Direct VPC Egress assigns your Cloud Run service a VPC IP address directly. The service becomes part of your VPC network.
# Deploy with Direct VPC Egress
gcloud run deploy my-service \
--network projects/PROJECT_ID/global/networks/VPC_NAME \
--subnet projects/PROJECT_ID/regions/REGION/subnetworks/SUBNET_NAME
When to use:
- You need the lowest possible latency
- You require VPC-native features (like custom routes)
- You're using Cloud Run (fully managed) with specific VPC requirements
The Conflict
Here's the problem: You cannot use both modes simultaneously. If your Cloud Run service already has a VPC Connector configured, and you try to deploy with Direct VPC Egress flags (or vice versa), you'll get this error:
ERROR: (gcloud.run.deploy) INVALID_ARGUMENT: VPC connector and direct VPC can not be used together
Why This Happens
The error occurs when:
- Existing service has one mode — Your service was previously deployed with a VPC Connector
- Deploy command specifies the other — Your new deploy command includes Direct VPC Egress flags
- GCP rejects the conflict — Cloud Run can't have both networking modes active
This is especially confusing because:
- The error message doesn't tell you which mode the service currently uses
- You might not remember how the service was originally deployed
- The conflict only appears during deployment, not in the console
How to Diagnose
Check Current Configuration
First, check what networking mode your service is currently using:
# Get the current service configuration
gcloud run services describe SERVICE_NAME \
--region REGION \
--format="yaml(spec.template.metadata.annotations)"
Look for these annotations:
VPC Connector mode:
run.googleapis.com/vpc-access-connector: projects/.../connectors/...
run.googleapis.com/vpc-access-egress: all-traffic # or private-ranges-only
Direct VPC Egress mode:
run.googleapis.com/execution-environment: gen2
run.googleapis.com/vpc-access-egress: all-traffic
# Plus network/subnet annotations
Check Your Deploy Command
If you're using Infrastructure as Code (Terraform, Pulumi, or YAML), check your configuration:
# service.yaml - VPC Connector mode
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: my-service
spec:
template:
metadata:
annotations:
run.googleapis.com/vpc-access-connector: projects/PROJECT/locations/REGION/connectors/CONNECTOR
run.googleapis.com/vpc-access-egress: all-traffic
vs.
# service.yaml - Direct VPC Egress mode
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: my-service
spec:
template:
metadata:
annotations:
run.googleapis.com/execution-environment: gen2
run.googleapis.com/vpc-access-egress: all-traffic
spec:
containers:
- image: gcr.io/...
How to Fix
Option 1: Remove the Conflicting Configuration
If you want to use VPC Connector, remove Direct VPC Egress flags:
# Remove network/subnet flags, keep VPC Connector
gcloud run deploy my-service \
--image gcr.io/PROJECT/service:latest \
--vpc-connector projects/PROJECT/locations/REGION/connectors/CONNECTOR \
--vpc-egress all-traffic
# NO --network or --subnet flags
If you want to use Direct VPC Egress, remove VPC Connector:
# Remove VPC Connector, use Direct VPC Egress
gcloud run deploy my-service \
--image gcr.io/PROJECT/service:latest \
--network projects/PROJECT/global/networks/VPC_NAME \
--subnet projects/PROJECT/regions/REGION/subnetworks/SUBNET_NAME
# NO --vpc-connector flag
Option 2: Update via YAML
Export the current service configuration, edit it, and apply:
# Export current config
gcloud run services describe SERVICE_NAME \
--region REGION \
--format export > service.yaml
# Edit service.yaml to remove conflicting annotations
# Remove either VPC Connector OR Direct VPC Egress config
# Apply the updated config
gcloud run services replace service.yaml --region REGION
Option 3: Clean Slate (Nuclear Option)
If you're stuck, delete and recreate the service:
# Delete the service
gcloud run services delete SERVICE_NAME --region REGION
# Deploy fresh with your chosen mode
gcloud run deploy SERVICE_NAME \
--image gcr.io/PROJECT/service:latest \
--vpc-connector projects/PROJECT/locations/REGION/connectors/CONNECTOR \
--vpc-egress all-traffic
Warning: This will cause downtime. Only use if the service can be safely recreated.
Real-World Example: Our Debugging Journey
Here's what happened to us:
- Initial setup: Service was deployed with VPC Connector for Memorystore Redis access
-
The change: Someone added
--networkand--subnetflags to the deploy script (thinking it would improve performance) - The problem: Deployments started failing with the conflict error. We tried various workarounds, thinking it was a transient issue
- The solution: Finally checked the existing service config, realized the conflict, removed the Direct VPC Egress flags
Lesson learned: Always check the current service configuration before changing networking settings.
Best Practices
- Document your networking mode — Add comments in your deploy scripts or IaC configs
- Use consistent patterns — Pick one mode per service and stick with it
-
Check before changing — Run
gcloud run services describebefore modifying networking - Prefer VPC Connector — Unless you have specific requirements, VPC Connector is simpler and more flexible
- Version control your configs — Keep service YAML files in git so you can see what changed
Quick Reference
| Mode | Flag | Use Case |
|---|---|---|
| VPC Connector | --vpc-connector |
Most common, managed service |
| Direct VPC Egress |
--network + --subnet
|
Low latency, VPC-native features |
Remember: You can only use one mode at a time. If you see the conflict error, check your existing service config and remove the conflicting flags.
More production GCP articles on my blog. I write about patterns from real infrastructure — find me at humzakt.github.io.
Top comments (0)