Describe what happened
Provider version: pulumi-cloudflare 6.4.1
Pulumi version: 3.181.0
Python version: 3.13
Description:
When replacing a ZeroTrustTunnelCloudflared resource with delete_before_replace=True, Pulumi reports the deletion as successful but the tunnel remains in Cloudflare. The subsequent create operation fails with a 409 Conflict error because the tunnel with that name still exists.
Steps to reproduce:
- Import an existing Cloudflare tunnel using
import_ option
- Remove the
import_ option and change a force-new property (e.g., tunnel_secret or config_src)
- Set
delete_before_replace=True in ResourceOptions
- Run
pulumi up
Expected behavior:
Pulumi should delete the tunnel from Cloudflare, then create a new one.
Actual behavior:
-- cloudflare:index:ZeroTrustTunnelCloudflared forgeit-infra deleted original (0.81s)
+- cloudflare:index:ZeroTrustTunnelCloudflared forgeit-infra replacing [diff: +configSrc,tunnelSecret]
++ cloudflare:index:ZeroTrustTunnelCloudflared forgeit-infra creating replacement error: 409 Conflict {"errors":[{"code":1013,"message":"You already have a tunnel with this name..."}]}
The tunnel was never deleted from Cloudflare despite Pulumi reporting "deleted original (0.81s)". Manual deletion via dashboard was required.
Possible causes:
- The Cloudflare API delete call may be failing silently (no error propagation)
- The tunnel may have active connections or DNS routes preventing deletion, but no error is surfaced
- The provider may not be checking the API response status
Sample program
# __main__.py
import os
import pulumi
from pulumi import ResourceOptions
from pulumi_cloudflare import Provider, ZeroTrustTunnelCloudflared
CLOUDFLARE_ACCOUNT_ID = os.environ["CLOUDFLARE_ACCOUNT_ID"]
CLOUDFLARE_API_TOKEN = os.environ["CLOUDFLARE_API_TOKEN"]
CLOUDFLARE_TUNNEL_SECRET = "c2VjcmV0LXRlc3QtdmFsdWUtMTIzNDU2Nzg5MA==" # base64 encoded
# Change this to "step2" after first successful run to trigger the bug
STEP = os.environ.get("STEP", "step1")
provider = Provider(
"cloudflare-provider",
api_token=CLOUDFLARE_API_TOKEN,
)
if STEP == "step1":
# Step 1: Create the tunnel normally
tunnel = ZeroTrustTunnelCloudflared(
"test-tunnel",
account_id=CLOUDFLARE_ACCOUNT_ID,
name="pulumi-bug-repro-tunnel",
tunnel_secret=CLOUDFLARE_TUNNEL_SECRET,
config_src="cloudflare",
opts=ResourceOptions(
provider=provider,
delete_before_replace=True,
),
)
else:
# Step 2: Change tunnel_secret to trigger replacement
tunnel = ZeroTrustTunnelCloudflared(
"test-tunnel",
account_id=CLOUDFLARE_ACCOUNT_ID,
name="pulumi-bug-repro-tunnel",
tunnel_secret="bmV3LXNlY3JldC12YWx1ZS1hYmNkZWZnaGlqaw==", # different secret
config_src="cloudflare",
opts=ResourceOptions(
provider=provider,
delete_before_replace=True,
),
)
pulumi.export("tunnel_id", tunnel.id)
Log output
No response
Affected Resource(s)
No response
Output of pulumi about
Run export PATH=$PATH:${HOME}/.pulumi/bin
CLI
Version 3.184.0
Go Version go1.24.5
Go Compiler gc
Host
OS ubuntu
Version 24.04
Arch x86_64
This project is written in python: executable='/usr/bin/python3' version='3.12.3'
Backend
Name x
URL file:///var/pulumi-state/x_workspace
User github-runner
Organizations
Token type personal
Pulumi locates its logs in /tmp by default
Additional context
No response
Contributing
Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).
Describe what happened
Provider version: pulumi-cloudflare 6.4.1
Pulumi version: 3.181.0
Python version: 3.13
Description:
When replacing a
ZeroTrustTunnelCloudflaredresource withdelete_before_replace=True, Pulumi reports the deletion as successful but the tunnel remains in Cloudflare. The subsequent create operation fails with a 409 Conflict error because the tunnel with that name still exists.Steps to reproduce:
import_optionimport_option and change a force-new property (e.g.,tunnel_secretorconfig_src)delete_before_replace=Truein ResourceOptionspulumi upExpected behavior:
Pulumi should delete the tunnel from Cloudflare, then create a new one.
Actual behavior:
The tunnel was never deleted from Cloudflare despite Pulumi reporting "deleted original (0.81s)". Manual deletion via dashboard was required.
Possible causes:
Sample program
Log output
No response
Affected Resource(s)
No response
Output of
pulumi aboutRun export PATH=$PATH:${HOME}/.pulumi/bin
CLI
Version 3.184.0
Go Version go1.24.5
Go Compiler gc
Host
OS ubuntu
Version 24.04
Arch x86_64
This project is written in python: executable='/usr/bin/python3' version='3.12.3'
Backend
Name x
URL file:///var/pulumi-state/x_workspace
User github-runner
Organizations
Token type personal
Pulumi locates its logs in /tmp by default
Additional context
No response
Contributing
Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).