# How auth0-deploy-cli Detects and Resolves Conflicts When Updating Resources

> Auth0-deploy-cli finds naming conflicts by comparing local assets with remote Auth0 resources and resolves them by temporarily renaming them before updates.

- Repository: [Auth0/auth0-deploy-cli](https://github.com/auth0/auth0-deploy-cli)
- Tags: internals
- Published: 2026-02-25

---

**The auth0-deploy-cli detects naming conflicts by comparing desired assets against existing remote resources in [`calculateChanges.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/calculateChanges.ts), then resolves them by temporarily renaming conflicting resources with random suffixes via the [`default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/default.ts) handler before applying updates.**

When managing Auth0 tenants through infrastructure-as-code, naming collisions frequently occur as resources are renamed locally while older versions persist remotely. The auth0-deploy-cli implements a deterministic conflict resolution mechanism that ensures idempotent deployments without manual intervention. This article examines the conflict detection logic in [`src/tools/calculateChanges.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/calculateChanges.ts) and the resolution strategy implemented in [`src/tools/auth0/handlers/default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/auth0/handlers/default.ts).

## Conflict Detection Logic in calculateChanges.ts

The conflict detection process begins in **[`src/tools/calculateChanges.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/calculateChanges.ts)**, where the `calculateChanges` function receives two parameters: the desired assets from local configuration (`assets`) and the current remote state (`existing`).

The function first categorizes assets into three lists: `create`, `update`, and `del`. When the identifier list includes **`name`**, the logic performs an additional collision detection pass:

1. Compiles "future assets" (resources scheduled for creation or update)
2. Compares these against existing resources not marked for deletion
3. Identifies collisions where `name` matches but primary identifiers differ

```typescript
// src/tools/calculateChanges.ts
if (identifiers.includes('name')) {
  const uniqueID = identifiers[0];
  const futureAssets: Asset[] = [...create, ...update];
  futureAssets.forEach((a) => {
    // skip if the colliding item will be deleted
    const inDeleted = del.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
    if (!inDeleted) {
      const conflict = (existing || []).filter(
        (e) => e.name === a.name && e[uniqueID] !== a[uniqueID]
      )[0];
      if (conflict) {
        // rename the existing conflicting resource with a temporary random suffix
        const temp = Math.random().toString(36).substr(2, 5);
        conflicts.push({
          ...conflict,
          name: `${conflict.name}-${temp}`,
        });
      }
    }
  });
}

```

When a conflict is detected, the system generates a temporary name by appending a random 5-character alphanumeric suffix (e.g., `my-client-a9x3p`) and adds the modified resource to the `conflicts` array.

## Conflict Resolution Strategy in default.ts

The **[`src/tools/auth0/handlers/default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/auth0/handlers/default.ts)** file contains the generic handler that processes the `conflicts` array returned by `calculateChanges`. This handler treats conflict resolution as a specialized update operation that must execute before other asset modifications.

The resolution process follows this sequence:

1. **Rename conflicting resources** – Update existing resources with their temporary suffixed names
2. **Process deletions** – Remove assets marked for deletion (if `AUTH0_ALLOW_DELETE` is enabled)
3. **Create new assets** – Add resources that don't exist remotely
4. **Update remaining assets** – Apply changes to non-conflicting existing resources

```typescript
// src/tools/auth0/handlers/default.ts
// Process Renaming Entries Temp due to conflicts in names
await this.client.pool
  .addEachTask({
    data: conflicts || [],
    generator: (updateItem) =>
      retryWithExponentialBackoff(() => {
        const updateFN = this.getClientFN(this.functions.update);
        const updatePayload = (() => {
          const data = stripFields({ ...updateItem }, this.stripUpdateFields);
          return stripObfuscatedFieldsFromPayload(data, this.sensitiveFieldsToObfuscate);
        })();

        return updateFN(updateItem[this.id], updatePayload);
      }, retryConfig)
        .then((data) => this.didUpdate(data as Asset))
        .catch((err) => {
          throw new Error(
            `Problem updating ${this.type} ${this.objString(updateItem)}\n${err}`
          );
        }),
  })
  .promise();

```

By renaming conflicting resources before creating new ones, the CLI ensures that name uniqueness constraints in the Auth0 Management API are never violated during the deployment process.

## End-to-End Conflict Resolution Flow

Understanding the complete flow helps clarify how auth0-deploy-cli maintains tenant consistency:

1. **Configuration parsing** – The CLI loads local YAML or directory-based configurations and constructs the desired asset state
2. **Remote state retrieval** – Each resource handler (e.g., [`clients.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/clients.ts), [`rules.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/rules.ts)) fetches existing assets from the Auth0 Management API
3. **Change calculation** – `calculateChanges` compares states and identifies conflicts where future assets share names with existing resources not scheduled for deletion
4. **Temporary renaming** – Conflicting existing resources receive random suffixes via the [`default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/default.ts) handler
5. **Asset synchronization** – The CLI proceeds with deletions, creations, and updates in that order
6. **Cleanup** – On subsequent runs, temporarily renamed resources that are no longer referenced in local configuration become candidates for deletion

## Practical Examples

### Basic Import with Automatic Conflict Resolution

When importing a client named `my-client` that already exists remotely under different metadata:

```bash
npm run build && node lib/index.js import -c config.json -i ./local/

```

The CLI automatically:
1. Detects the naming collision in [`calculateChanges.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/calculateChanges.ts)
2. Renames the remote client to `my-client-x1a9b` via [`default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/default.ts)
3. Creates the new `my-client` with updated configuration
4. Leaves the suffixed version for manual review or subsequent deletion

### Conflict Resolution with Deletions Disabled

Even when `AUTH0_ALLOW_DELETE` is set to `false`, conflict resolution still functions:

```bash
export AUTH0_ALLOW_DELETE=false
npm run build && node lib/index.js import -c config.json -i ./local/

```

In this scenario:
- The conflicting resource is renamed but not deleted
- Both the old (renamed) and new versions coexist in the tenant
- Subsequent deployments can remove the suffixed version if deletion is later enabled

### Programmatic Conflict Detection

For custom tooling or debugging, you can invoke the conflict detection logic directly:

```typescript
import { calculateChanges } from './src/tools/calculateChanges';
import { ClientHandler } from './src/tools/auth0/handlers/clients';

const handler = new ClientHandler(/* config & client */);
const desired = [ /* array of client definitions from YAML */ ];
const existing = await handler.getAll();   // remote state

const changes = calculateChanges({
  handler,
  assets: desired,
  existing,
  identifiers: ['client_id', 'name'],
  allowDelete: true,
});

console.log('Conflicts to rename:', changes.conflicts);

```

This returns the `conflicts` array containing the temporary-renamed representations that [`default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/default.ts) would process during a standard deployment.

## Summary

- **Conflict detection** occurs in [`src/tools/calculateChanges.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/calculateChanges.ts) by comparing future asset names against existing resources not scheduled for deletion
- **Temporary renaming** uses random 5-character suffixes (e.g., `resource-a9x3p`) to resolve naming collisions without data loss
- **Resolution execution** happens in [`src/tools/auth0/handlers/default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/auth0/handlers/default.ts) before deletions, creations, or standard updates
- **Idempotent deployments** are ensured by processing conflicts first, allowing the Auth0 Management API to maintain unique name constraints throughout the operation

## Frequently Asked Questions

### How does auth0-deploy-cli detect naming conflicts?

The CLI detects naming conflicts in [`src/tools/calculateChanges.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/calculateChanges.ts) by comparing the names of assets scheduled for creation or update against existing remote resources. When the identifier list includes `name`, the function checks if any future asset shares a name with an existing asset that has a different primary identifier and is not marked for deletion.

### What happens when a conflict is detected during import?

When a conflict is detected, the CLI generates a temporary name for the existing resource by appending a random 5-character suffix (e.g., `my-client-x1a9b`). This renamed resource is added to the `conflicts` array. During execution in [`src/tools/auth0/handlers/default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/auth0/handlers/default.ts), the CLI updates the existing resource with this temporary name first, freeing the original name for the new or updated resource.

### Can I disable automatic conflict resolution?

No, the conflict resolution mechanism is built into the core deployment logic and cannot be disabled through configuration flags. However, you can control whether the renamed (conflicting) resources are subsequently deleted by setting `AUTH0_ALLOW_DELETE=false`. This preserves both the old (renamed) and new versions in your tenant.

### Which resources support conflict detection?

Conflict detection applies to any resource handler that uses `name` as an identifier and inherits from the default handler in [`src/tools/auth0/handlers/default.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/src/tools/auth0/handlers/default.ts). This includes clients, resource servers, rules, hooks, and connections. Each resource-specific handler (such as [`clients.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/clients.ts) or [`rules.ts`](https://github.com/auth0/auth0-deploy-cli/blob/main/rules.ts)) invokes `calculateChanges` with appropriate identifiers to trigger the conflict detection logic.