cloudflare/cloudflared · error
%s already exists
Error message
%s already exists
What it means
writeTunnelCredentials saves the tunnel's JSON credentials file, but only when the destination does not already exist. If os.Stat finds an existing file at filePath (and stat itself succeeded), cloudflared refuses to overwrite it and raises this error, protecting existing credentials from being clobbered by a new tunnel's credentials.
Source
Thrown at cmd/cloudflared/tunnel/subcommands.go:304
warningChecker := updater.StartWarningCheck(c)
defer warningChecker.LogWarningIfAny(sc.log)
_, err = sc.create(name, c.String(CredFileFlag), c.String(createSecretFlag.Name))
return errors.Wrap(err, "failed to create tunnel")
}
func tunnelFilePath(tunnelID uuid.UUID, directory string) (string, error) {
fileName := fmt.Sprintf("%v.json", tunnelID)
filePath := filepath.Clean(fmt.Sprintf("%s/%s", directory, fileName))
return homedir.Expand(filePath)
}
// writeTunnelCredentials saves `credentials` as a JSON into `filePath`, only if
// the file does not exist already
func writeTunnelCredentials(filePath string, credentials *connection.Credentials) error {
if _, err := os.Stat(filePath); !os.IsNotExist(err) {
if err == nil {
return fmt.Errorf("%s already exists", filePath)
}
return err
}
body, err := json.Marshal(credentials)
if err != nil {
return errors.Wrap(err, "Unable to marshal tunnel credentials to JSON")
}
return os.WriteFile(filePath, body, 0400)
}
func buildListCommand() *cli.Command {
return &cli.Command{
Name: "list",
Action: cliutil.ConfiguredAction(listCommand),
Usage: "List existing tunnels",
UsageText: "cloudflared tunnel [tunnel command options] list [subcommand options]",
Description: "cloudflared tunnel list will display all active tunnels, their created time and associated connections. Use -d flag to include deleted tunnels. See the list of options to filter the list",
Flags: []cli.Flag{View on GitHub (pinned to 2253eeeb25)
Solutions
- Delete or move the existing file at the credentials path, then re-run the create/token command.
- If the existing file belongs to a still-valid tunnel, use it directly instead of creating a new tunnel.
- Point the command's --credentials-file (or output path) at a fresh, unique location.
Example fix
// before cloudflared tunnel create my-tunnel # ~/.cloudflared/<id>.json already exists // after rm ~/.cloudflared/<old-id>.json # or back it up cloudflared tunnel create my-tunnel
Defensive patterns
Strategy: validation
Validate before calling
credPath := "/home/user/.cloudflared/<id>.json"
if _, err := os.Stat(credPath); err == nil {
return fmt.Errorf("credentials file %s exists; remove or reuse it", credPath)
} Prevention
- Remove or archive old credentials JSON before re-running `tunnel create`.
- Use unique credentials-file paths per tunnel.
- Treat an existing credentials file as a signal the tunnel may already exist — check `tunnel list` first.
When it happens
Trigger: `cloudflared tunnel create <name>` (or `token` command) writing credentials to a path where a file already exists — typically re-creating a tunnel whose credentials file survived a previous create, or using a credentials-file path that collides with another tunnel's file.
Common situations: Re-running `tunnel create` after a partial run; reusing a config's credentials-file path for a new tunnel; stale JSON left after the tunnel was deleted remotely but the local file kept.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- couldn't read tunnel credentials from %v
- No configuration file was found. Please create one, or use t
- possible conflicting configuration in %[1]s and %[2]s. Eithe
- error writing token credentials to JSON file in path %s
- the argument path must be a directory
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/7374acef34d58d1c.
Report an issue: GitHub.