> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Conflict Detection

> How kdx sync detects and handles conflicting changes between local YAML files and server state using sync state files and conflict resolution strategies.

## Overview

When multiple people work on the same Kodexa environment — some editing resources in the UI and others pushing changes from YAML files — conflicts can occur. The CLI uses **sync state files** to detect when a resource on the server has changed since your last pull.

This prevents accidental overwrites where one person's changes silently replace another's, giving you the chance to review and merge before pushing.

## How It Works

Each time you run `kdx sync pull`, the CLI records the `changeSequence` of every fetched resource in a state file at `.sync-state/<env>.yaml`. When you later run `kdx sync push`, the CLI compares the stored sequence against the server's current value:

| Stored state            | Server state     | What happens                                 |
| ----------------------- | ---------------- | -------------------------------------------- |
| No entry (never pulled) | Any              | Pushes normally — no baseline to compare     |
| Sequences match         | Same             | Pushes normally — no server-side changes     |
| Sequences differ        | Changed          | **Conflict** — resource skipped with warning |
| Entry exists            | Resource deleted | Pushes normally — recreates the resource     |

## Example Conflict Output

When a conflict is detected, you will see a warning like:

```text theme={null}
⚠️  CONFLICT data-definition/invoice-data — server changeSequence is 15
    but was 12 when last pulled on 2026-04-08. Skipping (use --force to overwrite)
```

The resource is skipped, and all other non-conflicting resources continue to be pushed normally.

## The `--force` Flag

Use `--force` to push conflicted resources anyway, overwriting server-side changes:

```bash theme={null}
kdx sync push --target my-org --env dev --force
```

<Warning>
  Using `--force` overwrites any changes made to the resource on the server since your last pull. Always review conflicts before force-pushing.
</Warning>

## Deletions Inside a Resource

Conflict detection decides whether a resource is safe to write. A separate comparison decides whether a resource changed at all — and in two regions, content removed from your YAML counts as a change that must be pushed:

| Resource type     | Authored region                                                                                                |
| ----------------- | -------------------------------------------------------------------------------------------------------------- |
| `data-definition` | `taxons` — a removed taxon, or any key removed from inside one, such as a taxon's only `validationRules` entry |
| `task-template`   | `metadata.properties`                                                                                          |

Remove content from either region and push again: the resource is reported as changed and the content is removed on the server, so turning a setting off no longer requires writing it out explicitly as `false`.

Absence is not authorship — only a region your file actually authors is compared for removed keys:

* A file that omits `metadata.properties` entirely leaves properties set in the UI untouched.
* An explicit `metadata: {}` or `properties: {}` states that everything below it is empty, and clears it.
* A bare `taxons:` with no value — the natural result of commenting out every taxon — is treated as unmanaged, not as a deletion. An explicit empty list, `taxons: []`, is the delete-all spelling and does remove every taxon.

Everywhere else in the resource, push keeps its containment comparison: server-managed fields your file never mentions, such as `id`, `changeSequence` and `ref`, are ignored so they never mark a resource dirty.

<Note>
  Deletions inside these regions converge on Kodexa platform (V2) environments. Legacy environments keep the previous behavior, where removing content compares as unchanged.
</Note>

## Sync State Files

State files are stored at `.sync-state/<env>.yaml` in your repository root, one per environment:

```yaml theme={null}
# Auto-generated by kdx sync — do not edit manually
schemaVersion: "1.0"
environment: dev4
url: https://dev4.kodexacloud.com
organization: my-org
resources:
  datadefinition/invoice-data:
    changeSequence: 12
    pulledAt: "2026-04-08T20:00:00Z"
  dataform/invoice-review:
    changeSequence: 7
    pulledAt: "2026-04-08T20:00:00Z"
  tasktemplate/accounts-payable/invoice-review:
    changeSequence: 3
    pulledAt: "2026-04-08T20:00:00Z"
```

<Tip>
  **Commit state files to git.** This allows your team to share the same baseline — if one person pulls and commits the state file, others will get conflict detection even without pulling themselves.
</Tip>

## Recommended Workflow

For teams where some users edit resources in the Kodexa UI while others manage YAML files:

```bash theme={null}
# 1. Pull latest state from the environment
kdx sync pull --target my-org --env dev
git add .sync-state/ kodexa-resources/
git commit -m "Sync from dev: $(date)"

# 2. Make your YAML changes
vim kodexa-resources/data-definitions/invoice-data.yaml

# 3. Dry-run to check for conflicts before pushing
kdx sync push --target my-org --env dev --dry-run

# 4. If no conflicts, push
kdx sync push --target my-org --env dev

# 5. If conflicts detected, re-pull to get latest, then merge
kdx sync pull --target my-org --env dev
# Review changes, resolve any differences in YAML files
kdx sync push --target my-org --env dev
```

## Environment Name Resolution

The state file name is derived from the environment:

* `--env dev4` creates `.sync-state/dev4.yaml`
* `--to-url https://dev4.kodexacloud.com` creates `.sync-state/dev4.kodexacloud.com.yaml`
* `--to-profile myprofile` derives the name from the profile's URL

This means each environment's state is tracked independently — a conflict on `dev4` has no effect on pushes to `staging`.
