cloudflare/cloudflared · error
there should only be 1 non-deleted Tunnel named %s
Error message
there should only be 1 non-deleted Tunnel named %s
What it means
findIDs resolves multiple tunnel names to UUIDs using a single Tunnelstore API call per non-UUID input. The API contract assumes a tunnel name maps to exactly one non-deleted tunnel; when the filtered list returns a count other than 1, cloudflared cannot disambiguate and raises this error.
Source
Thrown at cmd/cloudflared/tunnel/subcommand_context.go:395
}
// findIDs is just like mapping `findID` over a slice, but it only uses
// one Tunnelstore API call per non-UUID input provided.
func (sc *subcommandContext) findIDs(inputs []string) ([]uuid.UUID, error) {
uuids, names := splitUuids(inputs)
for _, name := range names {
filter := cfapi.NewTunnelFilter()
filter.NoDeleted()
filter.ByName(name)
tunnels, err := sc.list(filter)
if err != nil {
return nil, err
}
if len(tunnels) != 1 {
return nil, fmt.Errorf("there should only be 1 non-deleted Tunnel named %s", name)
}
uuids = append(uuids, tunnels[0].ID)
}
return uuids, nil
}
func splitUuids(inputs []string) ([]uuid.UUID, []string) {
uuids := make([]uuid.UUID, 0)
names := make([]string, 0)
for _, input := range inputs {
id, err := uuid.Parse(input)
if err != nil {
names = append(names, input)
} else {
uuids = append(uuids, id)View on GitHub (pinned to 2253eeeb25)
Solutions
- Run `cloudflared tunnel list` and resolve duplicates: delete or rename extra tunnels with the same name.
- If zero results, check spelling and account (cert.pem must belong to the account owning the tunnel).
- Use the tunnel's UUID directly instead of the name to avoid ambiguity.
Example fix
// before cloudflared tunnel delete staging // ambiguous or missing // after cloudflared tunnel list cloudflared tunnel delete <exact-tunnel-uuid>
Defensive patterns
Strategy: validation
Validate before calling
out, _ := exec.Command("cloudflared", "tunnel", "list", "--output", "json").Output()
var tunnels []struct{ Name string }
json.Unmarshal(out, &tunnels)
count := 0
for _, t := range tunnels { if t.Name == name { count++ } }
if count != 1 { return fmt.Errorf("expected exactly 1 tunnel named %s, found %d", name, count) } Prevention
- Keep tunnel names unique in your account; delete or rename stale duplicates.
- Use UUIDs when operating on multiple tunnels in one command.
- Audit `cloudflared tunnel list` output in automation before batch operations.
When it happens
Trigger: Calling commands that accept multiple tunnel names (e.g. `cloudflared tunnel delete <name1> <name2>` or cleanup) where a name matches zero or more than one non-deleted tunnel in the account.
Common situations: Duplicate tunnels created under the same name in different environments sharing one account; the name was already deleted (list returns 0); race where a duplicate tunnel was created concurrently.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- %s is neither the ID nor the name of any of your tunnels
- there should only be 1 non-deleted virtual network named %s
- ErrNoTunnelID
- ErrInvalidTunnelID
- errDeprecatedClassicTunnel
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/a61164b6c00a6add.
Report an issue: GitHub.