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

  1. Delete or move the existing file at the credentials path, then re-run the create/token command.
  2. If the existing file belongs to a still-valid tunnel, use it directly instead of creating a new tunnel.
  3. 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

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


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/7374acef34d58d1c. Report an issue: GitHub.