Duplicates and conflicts

Most of what makes ImportKit safe to re-run lives here. Four of the five import types recognise data that already exists, and you decide per import what should happen to it.

What counts as “already exists”

Each type has its own identity. Two rows with the same identity are the same thing, and a row whose identity matches something in your store is a collision.

TypeIdentity
Metafield definitionsownerType + namespace + key
Metafield valuesowner_type + owner_reference + namespace + key
Metaobject definitionstype
Metaobject entrieshandle, within the target definition
Blog articlesnone — every row is a new article

That last row is the exception that matters: blog articles have no identity, no conflict mode and no pre-import check. Re-running an article file creates the articles again.

The three modes

The selector sits on the check step, labelled “If a definition already exists” or similar depending on the type. It applies to the whole import.

Skip — leave it unchanged Default

The existing thing is left completely alone. The row reports as a skip, and isn't charged.

This is the default because its worst case is that nothing happens. Use it when:

Update — patch it with this row's values

The existing thing is modified to match your row. Charged, because it's a write.

What “patch” means depends on the type, and the differences are deliberate — see per-type update behaviour. Use it when:

Update overwrites, and can't be undone

The previous values are gone — ImportKit doesn't keep them and can't put them back. Run the check first: for metafield values it shows the value currently in your store next to each row, so you can see exactly what you're about to replace.

Fail — report it as an error

The collision is treated as a row-level error. Nothing is written and nothing is charged.

Useful when a collision means something has gone wrong upstream:

Think of it as an assertion. In Fail mode a clean run means “everything in this file really was new”.

Choosing quickly

What you're doingMode
First import into a fresh storeSkip — the setting won't matter, and Skip is safe if it does
Adding fields or entries to a store that already has someSkip
Correcting values you imported beforeUpdate
Re-syncing from an external source of truthUpdate
Finishing a cancelled or interrupted importSkip, then Retry
Verifying a file contains nothing that already existsFail
Not sure yetSkip, run the check, read the report, then decide

Re-checking under a different mode is free, so you can compare all three before committing.

Screenshot

The conflict mode selector

The selector open with all three options and their help text, ideally with the check results behind it showing skips that would become updates.

assets/screenshots/conflict-mode-selector.png

Per-type update behaviour

“Update” isn't one behaviour. Shopify makes some things immutable, and rewriting others from a CSV would be destructive, so each type patches what it safely can.

Metafield definitions

Name, description, pin, access settings and validations are overwritten with your row's values. The type is never changed.

A row whose type differs from the existing definition is a conflict in every mode, including Update, and reports:

conflict
already exists as "single_line_text_field" but this row says "multi_line_text_field"

Shopify makes metafield types immutable — existing values are stored in that shape. To change a type, create a new definition under a different key and migrate the values.

Metaobject definitions

New fields are added. Existing fields are never rewritten. A row whose field type differs from the existing field produces a warning rather than an overwrite.

Field types are immutable and entries already hold data in them, so silently rewriting a definition's structure from a spreadsheet would be the most destructive thing this app could do. It doesn't.

The useful consequence: adding a field to an existing definition works well. Re-import the row with the new field in the fields cell, in Update mode, and only the addition happens.

Metaobject entries

The fields you mapped are overwritten on the existing entry, matched by handle. Fields not present in your file are left as they are.

This makes entries the best-behaved type for an ongoing sync: keep handles stable, re-export, re-import in Update mode.

Metafield values

The value is replaced. The check shows the current value first, which is the safeguard for a bulk overwrite.

Remember that blank cells are skipped rather than written, so Update mode can't blank a value out. Deleting a metafield is admin work.

Duplicates inside one file

Conflict modes are about collisions with your store. Collisions within the file are handled separately, and always the same way: the first occurrence is processed normally, and every later one is flagged.

report
Row 47 — duplicate of row 12

This is caught by the pre-import check, before anything runs. It's a common symptom of concatenating exports, or of a spreadsheet fill-down going one row too far. Because the check spots it, you can fix the file for free instead of discovering it as a mid-import collision.

Files too large to check

In-file duplicate detection is part of the check, so it isn't available above 50,000 rows. Those rows still can't create two of the same thing — the first one writes, and the second collides with it and follows your conflict mode. You just won't be warned in advance.

Conflict mode and Retry

Retry resumes a job using the conflict mode it was started with, and only touches rows that were never attempted. Rows that already succeeded are not revisited, so retrying can't double-write or double-charge.

Seeing all three, in one minute

Import any definitions file. Then upload the same file again, and press Re-check once per mode:

ModeReportCredit costStore changes
SkipAll rows skip0None
UpdateAll rows updateOne per rowValues patched
FailAll rows conflict0None

All three checks are free, and none of them writes anything.

Next