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

> ## Agent Instructions
> Ready for Commerce is an ecosystem that currently contains two products, PIM and Repricer, standing on one shared foundation: one identity, one organization, one team, one bill. Do not call it a platform with features, and never hint at an unreleased product.
> PIM connects to Shopify, Amazon, Square, Google Merchant Center and BigCommerce. Repricer connects to Amazon, Walmart, Shopify, BigCommerce, eBay and Square. The two products do not share one list, and each integration is authorized separately inside each product. The roster grows on purpose, so describe what the product does and let a table carry which integrations do it today, instead of counting them or writing that only one does something.
> Integration is the word this product uses, and it is the default in the documentation: the connection, the account, the Integrations screen, the per-account settings and the sync state are all integrations. Channel is reserved for the narrow sense of a destination where a listing lives, as in a product being live on a channel or archived on the channel.
> Newegg is not a supported channel. Do not describe it.
> On Amazon, PIM manages the offer only: price, availability and condition. It does not publish listing content such as titles, descriptions, images or specifications.
> Sign-in is passwordless: a single-use code emailed to the user, or Google. There are no passwords anywhere, so never describe a password, a sign-up with a password, or an email confirmation link.
> There is no public API for customers and no customer-facing webhooks. There is no organization-wide activity feed and no audit export, but the PIM does keep version history on products, brands, categories, tags and specifications, with who changed what and a restore, so never write that changes are not recorded or that an edit cannot be undone. Do not describe capabilities that are not documented here.
> Never write that the products have no AI, and never write that anything is AI-powered. Both are wrong. The PIM's image Optimizer runs AI-backed transforms the seller starts on purpose: Upscale, Remove background, and the region selection behind Refine. The Repricer reads competitor prices off web pages on the server. No control, badge or tooltip in either product names AI, and the seller never writes a prompt, so describe what the buttons do in the app's own words instead of reaching for the word.
> A PIM product, brand, category or variant can be switched off per connected integration account. Hover the channel badge and the switch is beside the account name in the card that opens. It carries no visible caption, so never call it the Sync switch: Sync is only its accessible name. On a variant-grained provider, Amazon today, the switch moves into the variant editor. On a product it asks whether to delete it from the channel, archive it there, or leave it live. Disabling stops publishing, not reading. There is still no per-field sync toggle.
> The PIM's image Optimizer replaced a feature called Squarify, which no longer exists. It resizes to an aspect ratio or to exact dimensions, removes backgrounds, upscales, trims the transparent margin around a cutout and re-centers it, pads, fills and re-encodes, and it always publishes a new asset instead of changing the original. Nothing crops into the picture: the subject is always contained whole.
> The PIM has no repricing engine and never reacts to a competitor's price. It does build the price it publishes to each integration account from the seller's own fields, configured in that account's settings, so do not write that the PIM has no pricing rules.
> Neither product has an in-app notification center, bell or inbox. Notifications are delivered by email only.
> Billing is per organization and per product, and only the organization owner can see or change it. Team members are free and uncounted, so never describe seats or per-user pricing.
> The seller never picks a plan. Each product has twelve price tiers assigned automatically from usage: the PIM from catalog product count, which includes drafts and archived products, and the Repricer from trailing 30-day sales. Nothing is feature-gated by plan and exceeding a tier never blocks work, so never write that a feature requires a higher plan.
> A subscription that is past due or paused makes the product read-only, which stops repricing and blocks edits without deleting data. Only a canceled subscription locks the seller out. Nothing is ever charged without a payment method on file.
> Pages containing the text 'This page has not been written yet', or its Spanish equivalent 'Esta página todavía no está escrita', are placeholders. Do not treat their headings as documented behavior.

# Imports

> An import loads a spreadsheet into your catalog, so you can add or change hundreds of products at once instead of opening them one by one.

An import reads a spreadsheet and writes what is inside it into your catalog. You give the PIM a CSV or an XLSX file. You tell it which column of your file feeds which field, and it works through your rows one at a time. When it finishes you get a copy of your own file back with two extra columns saying what happened to each row.

Most people import for one of three reasons. The first is to load your catalog into the PIM. The second is to change hundreds of your products at once instead of opening them one by one. The third is to send back a file you exported and edited in a spreadsheet. An import can add records, change records, empty chosen fields on records, or delete records, and you pick which of those four it does.

You will find all of this under `Uploads`, in the `Imports` tab. The `Create import` button above the table opens a dialog over the page that takes you through the file. The table under it lists every import your team has run, with a status and four counters on each one.

One file writes one kind of record. You choose from eight kinds, and products is where most people start.

## Before you start

Three things matter before your first import. Everything else on this page can wait until you need it.

### What your role lets you do

| Role | Create or cancel an import | Download the Results file |
| --- | --- | --- |
| Admin | Yes | Yes |
| Manager | Yes | Yes |
| Editor | No | Yes |

Below Manager, the `Create import` button above the table is not shown to you at all. You can still open any import in the table and download its Results file. Roles are set in [team, roles and permissions](/team#what-each-pim-role-can-do).

An Editor on your team is the case that surprises people. An Editor can export but cannot import, so an Editor sees a `Create export` button on the `Exports` tab and no `Create import` button here.

### There is no undo

<Warning>
  Nothing reverses an import. There is no rollback and no undo button, and if you cancel one halfway, every row it already wrote stays written.
</Warning>

Nothing shows you which rows would fail before you run it either. You find out after the fact, from the Results file, once the writing has already happened. So import a handful of rows first, read the Results file, fix whatever it flags, and only then send the whole thing. A 20-row test costs you two minutes and is the only preview there is.

### Import in the right order

Your file can only point at categories and specifications that already exist. Import a products file naming a category you do not have and the product goes in without that category. The PIM will not invent a place in your category tree from a cell in a spreadsheet. Brands and tags are different: those two are flat lists of names, so a products import can create them for you.

To load a catalog from nothing, work in this order:

1. Categories
2. Spec groups
3. Spec definitions
4. Spec values
5. Products

## How to import a file

<Steps>
  <Step title="Open the import dialog">
    From `Uploads`, select the `Imports` tab and click `Create import` above the table.
  </Step>

  <Step title="Choose what you are importing">
    The first screen inside the dialog is called `Entity`. It shows eight cards, one for each kind of record. Click `Products`, or click whichever card matches your file.
  </Step>

  <Step title="Add your file">
    On `File`, drag your file onto the drop area, or click `Upload new` to pick one from your computer. A preview of your first rows appears under it once the file is read.
  </Step>

  <Step title="Pick the mode">
    `Mode` shows four cards. Click `Create` to add records that are not in your catalog yet.
  </Step>

  <Step title="Map your columns">
    `Columns` lists your catalog's fields down the left. Each field has a dropdown on the right with your file's column names in it, so pick the column that feeds it. Anything the PIM recognized is already filled in for you.
  </Step>

  <Step title="Set the options">
    On `Options`, decide what should happen to a row that names a brand or a category you do not have. You can leave everything here alone the first time.
  </Step>

  <Step title="Check the summary and submit">
    `Summary` lists back everything you chose. Read it, then click `Submit` in the bottom right of the dialog.
  </Step>
</Steps>

That is the whole flow. Your import appears at the top of the table right away and moves through a few statuses while it runs. It ends with a count of successful rows, warnings, errors and blocked rows. A small message pops up wherever you are in the app when it finishes.

Everything below explains those screens one at a time, and then how to read what came back. You do not need any of it for a first import of a small file.

## Every option in detail

The dialog has eight screens in total: `Entity`, `File`, `Mode`, `Match Rules`, `Columns`, `Options`, `Clean Fields` and `Summary`. You never see all eight, because the mode you pick decides which ones apply to you.

| Mode | Screens you see |
| --- | --- |
| `Create` | `Entity`, `File`, `Mode`, `Columns`, `Options`, `Summary` |
| `Update` | `Entity`, `File`, `Mode`, `Match Rules`, `Columns`, `Options`, `Summary` |
| `Clean` | `Entity`, `File`, `Mode`, `Match Rules`, `Clean Fields`, `Summary` |
| `Delete` | `Entity`, `File`, `Mode`, `Match Rules`, `Summary` |

`Clean` and `Delete` skip both `Columns` and `Options`, so in those two modes the values inside your cells are never read at all. Only the columns your match rules point at matter. The `Tags` card never shows `Options` in any mode, because a tag has nothing to configure.

The step markers along the top of the dialog only take you backwards. `Next` is in the bottom right and stays gray until the screen you are on is complete, and the sections below say what each screen counts as complete.

Nothing you set up is saved anywhere, so reloading the page loses the whole setup and puts you back on `Entity`. Closing the dialog asks you to confirm first, with `Discard` and `Keep editing`, and discarding deletes the file you uploaded. While a submit is in flight the dialog will not close.

### Step 1: Choose what you are importing

`Entity` shows eight cards. Each card is one kind of record, and your file writes that kind and nothing else. Change this card later and you reset every screen after it.

| Card | Use it for |
| --- | --- |
| `Products` | Your products and their variants, with prices, stock, images and specifications |
| `Brands` | Brand names, descriptions, logos and their web addresses |
| `Categories` | Your category tree, one full path per row |
| `Tags` | Tag names and descriptions |
| `Spec Groups` | The top level of your specifications, and the categories each group applies to |
| `Spec Definitions` | The middle level, such as `Color` inside a group called `Appearance` |
| `Spec Values` | The allowed values under a definition, such as `Red` |
| `Assets` | Images and documents pulled in from web addresses, and where each one attaches |

If you are not sure which of the last three you want, [specifications](/pim/catalog/specifications) explains what a group, a definition and a value each are.

### Step 2: Add your file

`File` is where your spreadsheet goes in. Drag it onto the drop area, or click `Upload new` to browse your computer. If the file is on the web instead, click `From URL` next to it. A small dialog opens with a `URL` field, and pasting a direct download address there fetches the file.

A bar shows your upload moving, and a preview table appears once your file has been read. You see at most 10 rows of it, however many your file has. The preview is there to prove the PIM read your file the way you expected, not to show you your data.

Three controls are above that preview, and `Next` turns on once the preview has found at least one column in your file.

| Control | What it does |
| --- | --- |
| `First row is a header` | A switch. On means row 1 has your column names. Turn it off and row 1 becomes data |
| `Sheet` | A dropdown, and it only appears when your XLSX has more than one sheet with data in it |
| The drop area itself | Drop a second file on it at any time and the first one is thrown away |

**Leave `First row is a header` on unless your file genuinely has no header row.** Turning it off renames every column to `Column A`, `Column B` and so on. The later screens then map against those names. Because the names change, turning the switch off clears any match rule and any column mapping you had already set.

<Accordion title="How your column names are worked out, and what happens to odd ones">
  In a CSV, the header row is the first line that is not blank, so leading empty lines do not throw the reading off. In an XLSX it is the first physical row, blank or not.

  | Your file has | You get |
  | --- | --- |
  | Two columns with the same header | `Name` and `Name (2)` |
  | A blank header cell | `column_3`, counting the columns from one |
  | Cells past the last column that has a header | Nothing. They are dropped |
  | Blank rows in the middle | Nothing. They are skipped |

  You never pick the character that separates values in a CSV. It is found for you, and comma, semicolon, tab, pipe, backslash, caret and tilde are all recognized. Text is read as UTF-8, and a character that cannot be read is replaced with a placeholder mark instead of failing the file.
</Accordion>

### Step 3: Pick the mode

`Mode` shows four cards. The mode decides whether your rows create something, change something, empty something or destroy something.

| Mode | What it does to each row |
| --- | --- |
| `Create` | Inserts it. A row whose record already exists is an error, and never turns into an update on its own |
| `Update` | Finds the record and rewrites the fields you mapped. A row that matches nothing is an error |
| `Clean` | Finds the record and empties every field you checked on `Clean Fields`. Nothing else is touched |
| `Delete` | Finds the record and deletes it, with the same checks the delete button in the catalog makes |

**Pick `Create` for a catalog you are loading for the first time**, and for any file where every row is genuinely new. Pick `Update` when the records already exist and you want to change some of their fields. It is also the safe choice for a second attempt after a partly failed `Create`. Pick `Clean` when you want fields emptied and cannot express that in a cell, because an empty cell means "leave this alone" and never means "clear this". Pick `Delete` only when you are certain, because nothing brings the records back.

Change the mode later and you reset every screen after it.

<Danger>
  `Delete` mode is permanent. `Submit` turns red and a red banner appears above the summary saying records will be permanently deleted. One click is the whole confirmation, and you type nothing to confirm.
</Danger>

Delete a product and you lose its variants, along with its specification values and its category, tag and asset assignments. Nothing stops you deleting a product or an asset.

The other six kinds have a guard. A brand, category, tag, spec group, spec definition or spec value will not delete while something in your catalog still points at it. You get one error per row saying what is still attached. Detach those records first, or merge the record from your catalog instead.

How much one delete row removes depends on what it matched. A product has variants underneath it. Matching on a variant identifier and matching on a product identifier are two different instructions.

| Your row matched on | What gets deleted |
| --- | --- |
| Something a variant owns: SKU, barcode, ISBN, part number, custom identifier, or a variant ID | That variant alone |
| Something a variant owns, on a product's last remaining variant | The variant, and the product with it |
| Something the product owns: its slug, which is the handle in its web address, its title, or a product ID | The whole product, every [variant](/pim/catalog/variants) included |

### Step 4: Match your rows to records

`Match Rules` is how the PIM finds the record each of your rows is talking about. `Create` never touches a record you already have, so it never shows this screen. The other three modes all do, and none of them can run until you fill this in.

A rule pairs a target with one column of your file. The target is what kind of thing to look up, and the column is where your value comes from. Each rule is on its own card, labeled `Rule 1`, `Rule 2` and so on.

| On a rule card | What it does |
| --- | --- |
| `Single Match` | A radio button. The rule uses one target and one column |
| `Compound Match` | A radio button. The rule uses two or more, and every one of them has to agree |
| The dropdown on the left of each row | Picks the target |
| The dropdown on the right of each row | Picks the column of your file that feeds it |
| `Add` | Adds another target to a compound rule |
| The handle at the top left of the card | Drag it to move the rule above or below another one |
| `Add rule` below the cards | Adds a whole new rule |

Your rules run top to bottom, and the first one that finds exactly one record is the one that applies. That is why the order matters and why you can drag the cards.

| What a rule found | What happens |
| --- | --- |
| Exactly one record | The rule matches and your row applies |
| More than one | The rule stops there. It does not fall through to the rule below |
| Nothing | Your row gets an error saying no matching record was found |

**Use `Single Match` with the most specific column you have.** A SKU or an ID identifies one record on its own. A single rule on either is all your file needs in most cases. Use `Compound Match` when no single column is unique in your catalog. In practice that means matching a product by SKU plus brand name, because the same supplier SKU turns up under two brands in your catalog. Switch a rule to `Compound Match` and the usual shape for that card is filled in for you.

Which targets you can pick depends on the card, and two of them behave differently from the rest.

| Card | Targets a single rule can use | Targets only a compound rule can use |
| --- | --- | --- |
| `Products` | `ID`, `SKU`, `Part Number`, `Barcode`, `ISBN`, `Custom`, `Slug`, `Title` | `Brand Name`, `Product Type` |
| `Brands` | `ID`, `Brand Name`, `Brand Slug` | None |
| `Categories` | `ID`, `Category Slug`, `Category Path` | None |
| `Tags` | `ID`, `Tag Name` | None |
| `Spec Groups` | `ID`, `Spec Group Name` | None |
| `Spec Definitions` | `ID`, `Definition Name` | `Group Name` |
| `Spec Values` | `ID`, `Value Name` | `Group Name`, `Definition Name` |
| `Assets` | `ID`, `Asset URL`, `Display Name` | None |

`Category Path` walks your tree from the top, so a cell reading `Electronics > Phones` finds the child and not just anything called `Phones`. `Asset URL` accepts both the address an export writes and the public address you see in the catalog. It ignores everything after the question mark in either, so a stale address in your file still resolves.

Three rules the dropdowns enforce for you, so that a rule you can build is a rule that can work:

- **`ID` never appears in a compound rule.** An ID already identifies one record, so adding a second target to your rule can only narrow the result to nothing.
- **A compound rule always keeps one identifying target.** A rule made only of `Brand Name` would match every product of that brand. While your rule has no identifying target, the dropdown gives you nothing else and the button that removes the last one is hidden.
- **The same target cannot appear twice in one rule.** A target already used by another row of your card disappears from the dropdown.

**Up to 2 rules are already set up when you first open this screen.** Your column names are compared against a list of names the PIM knows, ignoring capital letters and punctuation. So `Product ID`, `product_id` and `PRODUCT-ID` all go to the same target. If nothing is recognized you get one empty rule with a sensible target and a blank column for you to fill.

<Accordion title="The column names each card recognizes on its own">
  | Card | Names it recognizes |
  | --- | --- |
  | `Products` | `id`, `product_id`, `uuid`, `variant_id`, `variant_uuid`, `sku`, `variant_sku`, `seller_sku`, `item_sku`, `part_number`, `part_numbers`, `mpn`, `mpns`, `manufacturer_part_number`, `manufacturer_part_numbers`, `gtin`, `gtins`, `upc`, `upcs`, `ean`, `eans`, `barcode`, `barcodes`, `isbn`, `isbns`, `slug`, `handle`, `url_slug`, `product_handle`, `title`, `name`, `product_name`, `product_title` |
  | `Brands` | `id`, `brand_id`, `uuid`, `name`, `brand_name`, `brand` |
  | `Categories` | `id`, `category_id`, `uuid`, `category_path`, `path`, `full_path`, `breadcrumb`, `slug`, `category_slug`, `handle` |
  | `Tags` | `id`, `tag_id`, `uuid`, `name`, `tag_name`, `tag` |
  | `Spec Groups` | `id`, `spec_group_id`, `uuid`, `group_name`, `name`, `spec_group_name`, `spec_group` |
  | `Spec Definitions` | `id`, `spec_definition_id`, `uuid`, `definition_name`, `name`, `spec_name`, `attribute_name` |
  | `Spec Values` | `id`, `spec_value_id`, `uuid`, `value_name`, `value`, `spec_value`, `attribute_value` |
  | `Assets` | `id`, `asset_id`, `uuid`, `image_url`, `url`, `asset_url`, `file_url`, `display_name`, `name`, `asset_name`, `title` |

  When nothing matches, the target you get instead is `SKU` for products, `Brand Name` for brands, `Category Path` for categories and `Tag Name` for tags. On the three specification cards it is `Spec Group Name`, `Definition Name` and `Value Name`, and on assets it is `Display Name`.
</Accordion>

The `id` and `variant_id` columns an export writes are not fields you can map on `Columns`, and they do not need to be. Leave them in your file, point a rule at the `ID` target, and their values are read right out of the row. Either column finds your parent product.

A rule you have not finished shows its problem on the card, in red, and `Next` stays off until every card is clean.

| Message | What went wrong |
| --- | --- |
| `Compound rules require at least 2 match fields. Add another field or switch to Single Match.` | A compound rule with one target |
| `Duplicate target type within this rule. Change one of them.` | The same target twice in one compound rule |
| `Same as Rule 2: change target or column` | Two rules doing exactly the same thing |

### Step 5: Map your columns

`Columns` is where you connect your file to your catalog. It lists your catalog's fields down the page, in groups with a heading over each one, and every field has a dropdown to its right with your file's column names in it. You read it field to column, not column to field, so the list on the page is your catalog and not your spreadsheet.

The PIM fills in as much as it can the moment you arrive. Each of your column names is compared against a field's internal name, its English name, its name in your own language, and a list of older names. Capital letters and punctuation are ignored. The first field that matches takes it and each of your columns is used once. Nothing is matched loosely, so a column either matches or it does not, and a near miss like `Prod Title` stays unmapped.

<Warning>
  What you map is what gets imported. A column you did not map does not exist for that import, even when its header is spelled exactly like a field.
</Warning>

The reverse is true as well. A column you did map is read as the field you picked, whatever its header says. Point a column of descriptions at `Price` and every row fails on the price rules.

**A toolbar is pinned above the list.** It has a search box that narrows the list as you type. The chips beside it filter the list down to the fields you have mapped, or the ones you have not. Those chips count over the whole list and not over what you can see, so they double as a read-out of how far along you are. If a filter is hiding a field you still have to map, an orange line under the toolbar tells you so.

Each field shows what it needs from you.

| On a field row | What it means |
| --- | --- |
| A dotted underline on the name | Hover it for a short description and an example value |
| `Not mapped` | No column of yours feeds this field |
| `Required` | `Create` will not run until you map it |
| `Required (any)` | One of a small set has to be mapped, and any one of them is enough |

`Next` turns on once you have mapped at least one column and every field the mode requires.

| Card | `Create` requires | `Update`, `Clean` and `Delete` require |
| --- | --- | --- |
| `Products` | `Slug` and `Title` | Nothing |
| `Brands` | `Brand Name` | Nothing |
| `Categories` | `Category Path` or `Category Name` | Nothing |
| `Tags` | `Tag Name` | Nothing |
| `Spec Groups` | `Group Name` | Nothing |
| `Spec Definitions` | `Group Name` and `Definition Name` | Nothing |
| `Spec Values` | `Group Name`, `Definition Name` and `Value Name` | Nothing |
| `Assets` | `Asset URL`, which is hidden in the other three modes | Nothing |

The other three modes require nothing because your match rules already found the record. `Update` still has to map something. The screen will not advance while every field reads `Not mapped`, because an update that writes no field does nothing.

These are the fields a products file can write into.

| Group | Field | What it takes |
| --- | --- | --- |
| Basics | `Slug` | The URL handle. It groups all variants of one product, so repeat it on every variant row |
| Basics | `Title` | Set it on the main row of each product. Variant rows can leave it blank |
| Basics | `Description` | Plain text or HTML, worked out for you |
| Basics | `Features` | One or more, joined by the features separator |
| Basics | `Status` | `draft`, `active`, `unlisted`, or `archived` |
| Taxonomy | `Product Type` | Free text |
| Taxonomy | `Condition` | Any condition your catalog uses, written either the way it reads on screen or in lowercase with underscores |
| Taxonomy | `Brands` | One or more names, joined by the brands separator. The first becomes primary |
| Taxonomy | `Categories` | One or more full paths, as in `Electronics > Phones > Smartphones` |
| Taxonomy | `Tags` | One or more names, joined by the tags separator |
| Taxonomy | `Shopify Category` | A full path or a bare taxonomy ID, as in `aa-1-2` |
| Identifiers | `SKU` | One per variant, and no two variants can share one. Optional |
| Identifiers | `Part Numbers` | One or more. The first is primary |
| Identifiers | `Barcodes` | 8 to 14 digits each, with the check digit verified |
| Identifiers | `ISBNs` | 10 or 13 characters, with the check digit verified |
| Identifiers | `Custom Identifiers` | `Label=Value` pairs. The `=` is fixed |
| Assets | `Primary Image URL` | A web address. The file is downloaded and stored |
| Assets | `Gallery Image URLs` | Addresses joined by the gallery separator, order kept |
| Assets | `Resource URLs` | Addresses joined by the resources separator, any file kind |
| Pricing | `On-hand Cost` | `12.50`, or the per-currency form |
| Pricing | `Fallback Cost` | The cost to fall back on when no other cost is known |
| Pricing | `Price` | `29.99`, or the per-currency form |
| Pricing | `Compare Price` | The struck-through reference price |
| Pricing | `MAP` | Minimum advertised price |
| Pricing | `MSRP` | Manufacturer's suggested retail price |
| Inventory | `Track Inventory` | `true`, `false`, `yes`, `no`, `1`, or `0`. Mapped with an empty cell means true |
| Inventory | `Fallback Stock` | The only stock column you can write |
| Variants | `Option 1 Name` and `Option 1 Value`, and onward | The name of a variant axis and this row's value on it |
| Specifications | `Specifications` | Three parts per entry, as in `Lighting > Color > Red` |
| Dimensions | `Product Weight` and its unit | Units `g`, `kg`, `oz`, `lb`, or `ct` |
| Dimensions | `Product Length`, `Product Width`, `Product Height` and their units | Units `mm`, `cm`, `in`, or `yd` |
| Dimensions | `Shipping Weight`, `Shipping Length`, `Shipping Width`, `Shipping Height` and their units | The packed numbers, in the same units |
| SEO | `Meta Title` | The title a search engine shows |
| SEO | `Meta Description` | Around 160 characters |
| Customs | `Country of Origin` | A two-letter country code, as in `US` |
| Customs | `HS Code` | 6 to 13 digits |
| Extra | `Information Sources` | `Label=URL` pairs or bare addresses. Labels stop at 50 characters |
| Extra | `Internal Notes` | Up to 1,000 characters, never shown to a shopper |

You write per-currency prices inside a single cell, as `USD=29.99|EUR=27.50`. The currency matching your organization's default becomes the main price and the rest become per-market prices beside it.

Three columns are hidden from this screen in every mode, so you cannot map them even if your file has them. `Supplier Cost` and `Supplier Stock` are written by your [data sources](/pim/uploads/data-sources), and `On-hand Stock` is added up from your connected locations. [Inventory](/pim/catalog/inventory) sets out where each number comes from.

<Accordion title="The fields you map on the other seven cards">
  | Card | Fields |
  | --- | --- |
  | `Brands` | `Brand Name`, `Description`, `Websites` as `Label=URL` pairs up to a maximum of 10, `Logo URL`, `Banner URL`, `Resource URLs`, `Slug`, `Meta Title`, `Meta Description` |
  | `Categories` | `Category Path`, `Category Name` which is taken from the end of the path if you leave it out, `Description`, `Thumbnail URL`, `Banner URL`, `Resource URLs`, `Slug`, `Meta Title`, `Meta Description` |
  | `Tags` | `Tag Name`, `Description` |
  | `Spec Groups` | `Group Name`, `Description`, `Categories` as full top-down paths, since a leaf name on its own is rejected |
  | `Spec Definitions` | `Group Name`, `Definition Name`, `Is Required`, `Is Unique`, `Description`, `Excluded Categories` as full paths |
  | `Spec Values` | `Group Name`, `Definition Name`, `Value Name`, `Description` |
  | `Assets` | `Asset URL`, `Display Name`, `Alt Text`, `Assigned to`, `Reference`, `Role`, `Order` |

  An assets file writes one file and at most one attachment per row, so putting the same image on several products means repeating the row.

  | Field on the assets card | What to put in it |
  | --- | --- |
  | `Assigned to` | `product`, `brand`, or `category` |
  | `Reference` | A slug. It also takes a SKU for products, or a name for brands and categories |
  | `Role` | `primary`, `gallery`, `logo`, `banner`, `thumbnail`, or `resources` |
  | `Order` | A whole number, giving the position within that role |
  | `Display Name` | Leave it blank and you get the file name from the end of the address |
</Accordion>

### Step 5: What an empty cell does

An empty cell and a missing column are not the same thing, and the difference decides whether an update leaves a field alone or wipes it.

| Your file | `Create` | `Update` |
| --- | --- | --- |
| A column you did not map | The field takes its default | The existing value is kept |
| A mapped column with a blank cell | The field takes its default | The existing value is kept |
| A money or dimension cell with `0`, `0.00`, `$0`, or `USD=0` in it | The field ends up empty | The existing value is cleared |
| `Fallback Stock` with `0` in it | The number zero | The number zero |

<Warning>
  A zero in a money or dimension cell is an instruction to clear the field, not a blank. A spreadsheet that filled its empty price cells with zeros wipes the prices it was meant to leave alone.
</Warning>

So a blank cell never clears anything. If clearing a field is what you actually want, that is what `Clean` mode is for.

One more thing about numbers. In a money or dimension cell a comma is read as a thousands separator and removed before the number is read. So `1,5` arrives as `15`, and `0,00` arrives as a zero that clears the column. Write `1.5` with a period instead, or use the per-currency form `EUR=1.5`, which is read the same way.

### Step 6: Set the options

`Options` decides how the PIM should behave in the cases your file did not cover. Most of it is questions with radio buttons, and the defaults are chosen so that nothing is created or destroyed behind your back. You can leave the whole screen alone on a first import.

**`Missing references` decides what happens to a row naming something you do not have.** Each question gives you `Skip with warning`, `Create automatically` and `Fail the row`, in that order. A question about a category or a specification drops the middle one.

| Card | Question | Choices | Default |
| --- | --- | --- | --- |
| `Products` | `If Brand does not exist:` | Skip, create, fail | `Skip with warning` |
| `Products` | `If Tag does not exist:` | Skip, create, fail | `Skip with warning` |
| `Products` | `If Category does not exist:` | Skip, fail | `Skip with warning` |
| `Products` | `If Shopify Category does not exist:` | Skip, fail | `Skip with warning` |
| `Products` | `If Spec Value does not exist:` | Skip, fail | `Skip with warning` |
| `Products` | `If Spec is not allowed for the product's categories:` | Skip, fail | `Skip with warning` |
| `Spec Groups` | `If Category does not exist:` | Skip, fail | `Skip with warning` |
| `Spec Definitions` | `If Spec Group does not exist:` | Skip, fail | `Skip with warning` |
| `Spec Definitions` | `If Category does not exist:` | Skip, fail | `Skip with warning` |
| `Spec Values` | `If Spec Definition does not exist:` | Skip, fail | `Skip with warning` |

`Skip with warning` imports the row without that one reference and records a warning against it. `Fail the row` rejects the row. `Create automatically` makes the missing brand or tag by name, and you only get that choice on those two. A brand and a tag are just names. A category or a specification has a place in a structure the PIM cannot guess.

**Set every question to `Fail the row` when you re-import a file you exported.** Nothing in that file should be missing. A question answered `Skip with warning` would let a real problem through with no message, and `Fail the row` shows it to you.

Two of these questions behave differently from the rest. A `Spec Definitions` row naming a group you do not have is dropped whole, even under `Skip with warning`. So is a `Spec Values` row naming a definition you do not have. There is nothing left of either row once the parent is gone. Setting those two to `Fail the row` only changes what the report calls it.

**`Update behavior` controls every field that takes more than one value at once**, such as the brands, categories, tags and specification values on a product. It appears on the `Products`, `Spec Groups`, `Spec Definitions` and `Assets` cards in `Update`, and on `Assets` in `Create`.

| Choice | What it does |
| --- | --- |
| `Replace` | Clears what is there and applies your file's set. This is the default |
| `Append` | Merges the two, drops duplicates, and leaves existing entries where they were |
| `Keep existing` | Ignores your file wherever the record already has a value. An empty one still gets filled |

Choose `Replace` when your file is the complete picture, which it is whenever you exported, edited and re-imported. Choose `Append` when your file only names the things you want to add, such as one new tag per product. Choose `Keep existing` when you are filling gaps and must not touch anything already filled in.

| Card | What the setting covers |
| --- | --- |
| `Products` | Brands, categories, tags, features, information sources and specification values |
| `Spec Groups` | The categories the group applies to |
| `Spec Definitions` | The excluded categories |
| `Assets` | Where each file is attached |

It does not cover images. `Primary Image URL`, `Gallery Image URLs` and `Resource URLs` always replace, which [assets](/pim/assets) explains from the library side. `Append` also behaves differently on a specification that allows only one value. Your file's value is rejected and the existing one is kept, and the rest of the row still saves with a warning.

**`Asset downloads` decides what a broken image address costs you.** It appears on the `Products`, `Brands` and `Categories` cards in `Create` and `Update`.

| Question | Default | The other choice |
| --- | --- | --- |
| `If an asset download fails:` | `Warn and continue` | `Fail row` |
| `If gallery has no primary image:`, products only | `Leave without primary` | `Promote first to primary` |

Leave `Warn and continue` on unless a product with a missing image is worse to you than no product at all. Picking `Fail row` on a products file rejects the whole product, so that row comes back as an error and the other rows of the same product come back as blocked.

**`If an asset already exists` decides whether a file you already have gets used again.** The PIM compares the contents of the file, not its address. So re-importing the same picture from a different link still finds it. On the `Products`, `Brands` and `Categories` cards you get `Reuse existing`, which is the default, and `Upload as new`. A standalone `Assets` import in `Create` gets three choices instead, because that file has its own display name and alt text. `Reuse, update labels` is the default, `Reuse, keep labels` leaves the old wording alone, and `Upload as new` makes a second copy.

**`Array value separators` sets the character that splits a cell with a list in it.** Each box takes up to 3 characters, and clearing a box puts the default back. `Next` stays off while any box looks empty. Change one only when your own data contains the default character, which is the one case where the default would split a value in half.

Two separators default to `>`: `Specs path` and `Category path`. The other fourteen default to `|`: `Tags`, `Features`, `Specs`, `Category list`, `Brands`, `Barcodes`, `ISBNs`, `Part Numbers`, `Gallery`, `Resources`, `Websites`, `Information sources`, `Custom identifiers`, and `Excluded categories`.

| Card | Separator boxes you see |
| --- | --- |
| `Products` | Tags, Features, Specs, Specs path, Category path, Category list, Brands, Barcodes, ISBNs, Part Numbers, Gallery, Resources, Information sources, Custom identifiers |
| `Brands` | Websites, Resources |
| `Categories` | Category path, Resources |
| `Spec Groups` | Category list, Category path |
| `Spec Definitions` | Excluded categories, Category path |
| `Tags`, `Spec Values`, `Assets` | None |

The `=` between a label and a value in a pair-style cell, such as `UNSPSC=43211503`, is fixed and nothing here changes it. Nothing here sets the character between your CSV's columns either, which is always found for you.

### Step 7: Pick the fields to clear

`Clean Fields` only appears in `Clean` mode, and it is the list of fields your import will empty on every record it matches. You get a checkbox per field, grouped the same way the mapping screen groups them, with the same search box and filter chips pinned above. Check at least one or `Next` stays off.

| Card | Fields you can clear |
| --- | --- |
| `Products` | Description, product type, condition, status, internal notes, meta title, meta description, Shopify category, brands, categories, tags, features, specifications, information sources, barcodes, ISBNs, part numbers, custom identifiers, price, compare price, on-hand cost, fallback cost, MAP, MSRP, track inventory, fallback stock, the eight product and shipping dimension values, country of origin, HS code, primary image, gallery images, and resources |
| `Brands` | Description, websites, logo, banner, meta title, meta description |
| `Categories` | Description, thumbnail, banner, resource files, meta title, meta description |
| `Tags` | Description |
| `Spec Groups` | Description, categories |
| `Spec Definitions` | Description, excluded categories |
| `Spec Values` | Description |
| `Assets` | Alt text |

Clearing the inventory pair on products leaves the product untracked with every stock number empty, so check those two together or not at all.

Some fields never appear on this screen, whatever you are looking for. Names and identifiers do not appear, because clearing what a record is found by would leave you no way to find it again. That covers `SKU`, `Slug` and a product's `Title`. It also covers the name of a brand, a category, a tag or a definition, the text of a value, and an asset's `Display Name`. The numbers the PIM maintains for you do not either, and those are `Supplier Cost`, `On-hand Stock` and `Supplier Stock`. Neither do the columns that always have something in them, such as the position and sort columns and every unit column.

### Step 8: Check the summary and submit

`Summary` is a panel called `Import Summary` listing back everything you chose, so read it before you click anything.

| Row | When you see it |
| --- | --- |
| `Entity`, `Mode`, `File` with its name and size | Always |
| `Sheet` | You picked one |
| `File format`, `Columns in file` | Always |
| `Mapped fields` | Every mode except `Clean` and `Delete` |
| `Match rules`, a count and then the rules themselves | Every mode except `Create` |
| `Fields to clear` | `Clean` only |
| `Update behavior` | `Update`, and `Create` on the `Assets` card |
| The missing-reference answers | The card asked them |
| `Asset download fail`, `Gallery no primary` | The card asked them |
| `Asset handling` | The card has it |
| One row per separator you changed | You changed one |

The rules are written the way the PIM reads them. A single rule on SKU shows as `sku`, and a compound rule on barcode plus brand shows as `gtin+brand_name`. When every missing-reference answer is the same and there are two or more, they collapse into one row reading `Skip with warning (all)`. Expect one oddity: a `Tags` import in `Update` shows an `Update behavior` row even though the `Tags` card never offered you the control.

`Submit` is in the bottom right and checks everything again, your match rules included, then starts the import without uploading your file a second time.

| What happens | Message |
| --- | --- |
| It started | `Import started successfully` |
| Something else of yours is running | `Import queued at position {position}. It will start when the current job finishes.` |
| Your file is too big | `File must be 476 MB or smaller` |
| Your setup did not pass the second check | `The import configuration is invalid. Please review the wizard steps and try again.` |
| More than 24 hours passed since you uploaded | `Upload draft not found or expired. Please re-upload the file.` |
| Nothing else worked | `Could not start the import. Please try again.` |

### Limits

| What | Limit |
| --- | --- |
| Formats you can upload | CSV and XLSX |
| Biggest file | 476 MB |
| Rows in a file | No limit |
| Monthly quota or rate limit | None |
| File name length | 255 characters |
| Rows in the preview | 10 |
| How long an unfinished upload lasts | 24 hours |
| Rules on one import | No limit |
| A separator you type | 3 characters |
| Variant option columns | 50 pairs |
| Websites on a brand | 10 |
| Internal notes on a product | 1,000 characters |
| Imports at once | One per organization. The rest wait in line |
| How long a finished import stays in the table | Forever |

### What an import cannot do

| You cannot | Do this instead |
| --- | --- |
| Undo one, or take back a row it already wrote | Import a correcting file |
| See which rows would fail before you run it | Import a few rows first and read the Results file |
| Download a sample file or a starter template | Export the records you are about to change and edit that file. See [exports](/pim/uploads/exports) |
| Save a column mapping and reuse it | Every run rebuilds the mapping from your column names |
| Schedule an import or repeat it every week | Set up a [data source](/pim/uploads/data-sources#how-to-set-up-a-data-source) |
| Retry one row, or fix a row from inside the import | Fix your file and import again |
| Have a failed import retried for you | Upload the file again yourself |
| Choose the character between your CSV's columns | It is found for you |
| Write stock or supplier cost | Connect a location or a [data source](/pim/uploads/data-sources) |

## How a products file has to be shaped

A products file is the one with a shape of its own. A spreadsheet has one row per line of data, and a product with variants is more than one line of data. Get the shape wrong and every row of a product fails together.

### One row per variant, grouped by slug

Every row of one product has the same `Slug`, and that is what tells the PIM the rows belong together. The first row of each group is the main product row: it has the `Title` and everything that describes the product as a whole. The rows after it are variant rows, and they can leave the product fields blank while giving their own option values.

- A product with a single variant and no options is **one row**, with everything on it.
- Anything else is **one main row, then one row per variant**. A product with 4 variants is 5 rows.

You need `Slug` on every row without exception, and it is never worked out from `Title`. A group with no main row fails, and so does a variant row with no option name cells, because neither one can be read as a variant of anything.

The simplest way to get the shape right is not to build it. Export the products first, edit the file you get, and send that back: an export already comes out in exactly this layout.

### Option columns

An option is a variant axis, such as `Color` or `Size`. Each one is a pair of columns: `Option 1 Name` names the axis and `Option 1 Value` gives this row's value on it, and `Option 2 Name` and `Option 2 Value` do the second axis, and so on.

You always get at least 3 pairs on the mapping screen, and more if your file has more, up to 50 pairs. Write the header as `Option 1 Name`, `option_1_name` or `option1_name` and all three are recognized. Every variant of one product has to list the same axes in the same order. No two variants can end up with the same combination of values.

### Columns that come out of an export and cannot go back in

Most of a products export goes right back in, column names and all. These are the ones that do not.

| Column | Why |
| --- | --- |
| `id`, `variant_id` | Your match rules read them from the row instead, and they are not fields you map |
| `on_hand_stock`, `supplier_stock`, `supplier_cost` | The PIM maintains these for you |
| `currency` | Per-currency prices ride inside the price cell instead |
| Position and sort-order columns | Ignored |
| Counts such as `product_count` | Ignored |
| `kind` on an asset row | Ignored. It is worked out from the file itself |

Leaving them in your file is harmless. They arrive unmapped and are dropped, so there is no need to strip an export before sending it back.

## When something goes wrong

### Watching your import run

Your import appears in the table right away and moves through these statuses:

| Status | What it means |
| --- | --- |
| `Queued` | Another import of yours is running. Yours has not started |
| `Pending` | Yours is waiting to be started |
| `Validating` | Your file is being read. Nothing is written yet |
| `Processing` | Rows are being written. You see a percentage |
| `Importing assets` | An `Assets` import is working through its downloads |
| `Finalizing` | Tidying up after the last row. You can no longer cancel |
| `Completed` | Done |
| `Failed` | Done, and nothing at all went in |
| `Cancelled` | Done, and whatever had been written stayed written |

One import runs at a time and the rest queue behind it, first in first out, so several of yours can be waiting. The percentage is the only progress you get: no time estimate, no rows a second, and no live list of errors. Nothing about what went wrong comes to you until the import finishes.

There is no partial status. An import with at least one success ends as `Completed` even if half the file failed, and `Failed` means nothing at all went in. So read the four counters, never the status alone.

An interrupted import restarts on its own within 2 minutes and one that was downloading images continues where it stopped. An import still running after 4 hours is marked `Failed` for you.

Wherever you happen to be in the app, a small message pops up when your import finishes, whether it completed, failed or was canceled.

### Canceling one

`Cancel` is a button at the end of the import's row in the table. It works while the import is queued, pending, validating, processing or importing assets, and not once it gets to `Finalizing`. On a row where it cannot be used, hovering it tells you why.

Canceling keeps every row already written. New image downloads stop within 1 second, and downloads already in flight finish and leave their files in your [asset library](/pim/assets) unattached to anything.

### Reading the imports table

| Column | What it shows |
| --- | --- |
| `File` | The file name. Quick search only looks in this column |
| `Entity` | Which of the eight kinds you imported |
| `Mode` | Which of the four modes you ran |
| `Status` | Where it is, with a percentage while it runs |
| `Success` | Rows that went in cleanly, in green |
| `Warnings` | Rows that went in with something worth reading, in orange |
| `Errors` | Rows that did not go in, in red |
| `Blocked` | Rows that were fine but were kept back, in gray |
| `Created at` | When it was started |
| `Created by` | Who started it |

A counter showing zero reads as a dash. All four sort and filter, and hovering a counter's heading tells you what it counts. The `Entity`, `Mode` and `Status` dropdowns above the table only list values your team has actually used, so a short list there is normal. If you find yourself building the same filters every week, [saved views](/pim/saved-views) keeps them for you.

<Info>
  A blocked row has nothing wrong with it. All the rows sharing a slug are one product and are written as a unit, so an error on any one of them keeps the whole product back.
</Info>

That is why fixing one real error often clears a dozen blocked rows at once. Warnings work the other way around. When a product saves and its main row collected warnings, every variant row is marked, so you open the main row.

### Getting the Results file

`Results` is a button at the end of the import's row in the table, next to `Cancel`. It turns on once the import finishes, and until then hovering it says so. Clicking it asks whether you want `CSV` or `Excel`, and then builds the file while you wait.

You get your original upload back with 2 columns added on the end, `result` and `message`, and one row out for every data row you sent in.

| `result` | What it means | What `message` says |
| --- | --- | --- |
| `error` | The row did not import | The errors, then blocked notes, then warnings |
| `blocked` | The row was fine, but another row of the same product failed | Blocked notes and warnings |
| `warning` | The row imported, and something is worth reading | The warnings |
| `success` | The row imported cleanly | Nothing |

Sort or filter the `result` column, errors first and blocked second. Row 1 in the report is the first data row of your file, and the header is not counted. So the numbers line up with your spreadsheet once you allow for that. A message names the kind of problem and not the value that caused it, so use the row number to find the cell.

The file is named after yours, as `catalog_results_2026-07-31.csv`, using the date the import was created. It is rebuilt every time you ask for it, so you can come back for it as long as the import is still in the table, which is forever. Closing the dialog while it builds does not cancel it. If it takes longer than 2 minutes you are told to click `Results` again in a moment to pick it up.

### The email you get

The email goes to whoever created the import and to no one else. You only get it when the import gets to `Completed`, so a failed or canceled one emails no one. There is no notification center in the app to check instead.

| Part of the email | What is in it |
| --- | --- |
| Subject | That the import is complete, and whether there were errors |
| Status | `All rows imported`, or `Completed with errors` |
| Details | `Total rows`, `Successful`, `Errors`, `Organization` |
| Button | `View products` |

It has no attachment and no link to the Results file, so the table is still where you go for that. The email is on by default and you can turn it off under `Import complete` in your notification settings.

### Errors before any row is read

These stop the file rather than a row, so nothing at all is written.

| Message | What went wrong |
| --- | --- |
| `Could not start upload` | The upload never began |
| `Upload failed` | The transfer did not finish |
| `The file is larger than the 476 MB upload limit` | Your browser checks the size before anything uploads |
| `Could not read file` | The preview could not be built |
| `Could not read sheet` | The sheet you picked could not be read |
| `This sheet has no data rows. Pick a different sheet from the selector.` | The sheet is empty below its header |
| `The file was read successfully but it has no data rows. Check that it contains data beyond the header row.` | Your file has a header and nothing else |
| `This file isn't a supported spreadsheet. Use a CSV or XLSX file.` | The file is not a spreadsheet at all |
| `The file was downloaded but couldn't be read as a spreadsheet. Check that it's a valid CSV or XLSX file.` | It looked right and still could not be read |
| `The file was downloaded but it's empty. Check that the right file is being published at that location.` | Usually a web address serving nothing |

Paste a web address that returns a page instead of a file and you get `That address returned a web page instead of a data file.` The message goes on to name the fix for the two services this happens on most.

| Service | What to change |
| --- | --- |
| Dropbox | Change `dl=0` to `dl=1` at the end of the link |
| Google Drive | Replace the trailing `/edit` and everything after it with `/export?format=xlsx` |

Some failures add a technical detail line under them, in a monospaced font below a dashed line. That line is for support, not for you.

### The errors you will actually see

These are the ones that come up on ordinary files. The accordions below have the rest, grouped by what they are about.

| Message | What to change |
| --- | --- |
| `A required field is missing on this row.` | A required cell is blank. On a products file you need `Slug` on every row, variant rows included |
| `No matching record was found in your catalog.` | The value in your match column does not exist yet. Import it with `Create`, or point the rule at a different target |
| `Multiple records matched. Provide a more specific identifier.` | Your rule is ambiguous. Switch to a compound rule or use a unique column |
| `This row already exists. Use UPDATE mode to modify it.` | You ran `Create` over records you already have |
| `A SKU is already in use elsewhere in your catalog. Pick a unique SKU, or use UPDATE mode.` | Another variant already has that SKU. A variant has at most one, and there is no product-level SKU |
| `An identifier failed checksum validation. Verify the digits.` | A barcode or an ISBN is the right length and its check digit does not add up. [Identifiers](/pim/catalog/identifiers) lists every rule |
| `The referenced brand was not found.` | A warning, not an error. Set the brand question to `Create automatically`, or import your brands first |
| `This row updates the same record as an earlier row of this file. Keep one row per record and re-import.` | Two of your rows point at the same record. The first applies and the rest error |
| `This row was not saved because another row in the same product (parent or variant) has errors. Fix the other errors and re-import.` | Nothing. Fix the real error and this row goes in on the next run |
| `This variant imported without problems, but the main product row has warnings. Review it.` | Nothing on this row. Go and read the warnings on the main row of that product |
| `Something went wrong. Please try again. If the problem persists, contact support.` | Import that row again. If it repeats, it is not your file |

<AccordionGroup>
  <Accordion title="Errors about the shape of a products file">
    | Message | What to change |
    | --- | --- |
    | `This product has no main product row. One row per product must carry the Title and leave the option value cells empty. Re-export the products to get a correctly shaped file.` | Your file has variant rows with no main row above them |
    | `A variant row carries no option name cells, so it cannot be imported as a variant. Map the option name and value columns (option1_name / option1_value) on every variant row, or remove the row.` | The row has values but no axis names |
    | `A variant must have a value for every option defined on its product.` | One variant is missing a value on one axis |
    | `A variant row is missing a value for one of its options.` | The same problem, seen from the cell |
    | `Variants of the same product must list the same option axes in the same order.` | Two rows of one product disagree about the axes |
    | `Two variants share the same option combination. Each variant must have a unique combination.` | Two rows describe the same variant |
    | `Cannot identify which variant of this product to update.` | Renaming a SKU or targeting one variant needs the row matched by `ID`, either a variant ID in an `ID` column or a `variant_id` column |
    | `Product columns were ignored because this file has no main product row for this product. To update product fields, import a file that includes the main product row.` | Add the main row, or accept that only variant fields change |
    | `This file uses the legacy export format. Re-export the products to obtain a re-importable file.` | Export the products again and edit the new file |
  </Accordion>

  <Accordion title="Errors about a value in a cell">
    | Message | What to change |
    | --- | --- |
    | `A field exceeds its maximum length.` | Shorten the cell |
    | `A field value is not one of the allowed options.` | The cell has something outside the list that field accepts |
    | `A yes/no field has an invalid value.` | Use `true`, `false`, `yes`, `no`, `1` or `0` |
    | `An integer field has an invalid value.` | A whole number is expected |
    | `A numeric field has an invalid value.` | Check for stray text or a comma used as a decimal point |
    | `A stock quantity is negative. Stock must be 0 or a positive whole number.` | Use zero |
    | `A unit is set but its measurement value is empty.` | Fill the measurement, or clear the unit beside it |
    | `A URL is malformed. URLs must start with http:// or https://.` | Add `http://` or `https://` to the front |
    | `A slug must contain at least one letter or digit.` | Give the row a real slug |
    | `An identifier value has an invalid format.` | Check the length of the barcode, ISBN or part number |
    | `Country of Origin must be a 2-letter ISO country code (e.g. US, CN, DE).` | Use the code, not the country name |
    | `HS Code must be 6 to 13 digits.` | Digits only |
    | `A field contains characters reserved for the spec cell format.` | Your value contains the character your separators use |
    | `The category path is empty or malformed. Use the full top-down path.` | Write the whole path from the top |
  </Accordion>

  <Accordion title="Errors about something the row points at">
    | Message | What to change |
    | --- | --- |
    | `The referenced category was not found.` | Import your categories first. A products import cannot create one |
    | `Multiple categories share this name. Provide the full path (e.g. "Parent > Child > Leaf") or add a slug column to disambiguate.` | Write the full path |
    | `A parent category in the path was not found. Import parent categories first.` | Import the tree from the top down |
    | `The referenced tag was not found.` | Set the tag question to `Create automatically`, or import your tags first |
    | `The referenced spec group was not found. Import spec groups first.` | Follow the order at the top of this page |
    | `The referenced spec definition was not found. Import spec definitions first.` | The same |
    | `The referenced spec value was not found. Import spec values first.` | The same |
    | `A required specification has no value on this product. Add a value, or make the specification optional.` | Fill it, or change the definition |
    | `A spec group is not allowed for this product's categories.` | Give the product one of the group's categories, or pick a spec from a group that fits |
    | `A spec definition is excluded for one of this product's categories.` | Pick a different spec, or take the conflicting category off the product |
    | `The Shopify category path / id was not found in the Shopify taxonomy.` | Check the path against the picker in the product editor |
  </Accordion>

  <Accordion title="Errors about something already existing">
    | Message | What to change |
    | --- | --- |
    | `A barcode is already in use elsewhere in your catalog.` | Barcodes are unique across your catalog |
    | `An ISBN is already in use elsewhere in your catalog.` | The same |
    | `A part number is already in use for one of the selected brands.` | Part numbers are unique per brand |
    | `A custom identifier is duplicated on the same variant.` | Two entries in one cell share a label |
    | `A custom identifier with the same label already exists with a different value.` | Decide which value is right |
    | `A URL is duplicated within the row.` | The same address appears twice in one cell |
    | `A sibling under the same parent already uses this name.` | Rename it, or move it under a different parent |
    | `A sibling under the same parent already uses this slug.` | The same, for the slug |
    | `SKU is single-valued and cannot be changed in Append mode.` | Set `Update behavior` to `Replace`, or edit the SKU in the catalog |
    | `This unique-spec definition already has a different value. The existing value was kept.` | A warning under `Append` on a single-value specification. Use `Replace` to overwrite it |
    | `A specification that allows only one value has more than one on this product.` | Keep one value, or let the definition take several |
  </Accordion>

  <Accordion title="Errors about images and files">
    | Message | What to change |
    | --- | --- |
    | `Could not download the source file. Verify the URL is publicly reachable.` | The address needs a sign-in, or it is wrong |
    | `Could not upload the asset. Please retry the import.` | Import that row again |
    | `Could not upload the asset: your storage quota is full.` | Delete files you no longer need, or move to a larger plan. See [billing](/billing) |
    | `The asset was uploaded but could not be assigned.` | The file is in your library. Attach it from there |
    | `The entity already has an asset for this role.` | Set `Update behavior` to `Replace`, or use a different role |
    | `This single-slot role already has an asset; Append mode cannot replace it.` | Set `Update behavior` to `Replace` |
    | `The entity already had an asset for this role and Keep behavior was selected.` | The new file is in your library, unattached. Switch to `Replace` to swap it in |
    | `The asset is already in your DAM library. The existing asset was assigned.` | Nothing. Your file was reused instead of copied |
    | `The asset already exists in your DAM library. CSV metadata was not applied.` | Pick `Reuse, update labels` if you wanted the file's name and alt text applied |
  </Accordion>

  <Accordion title="Errors and warnings about prices">
    Three of these block the row, and the rest let it through and go in the `Warnings` counter.

    | Message | Blocks the row |
    | --- | --- |
    | `Compare-at price must be greater than or equal to the price` | Yes |
    | `Price is below cost (negative margin)` | Yes |
    | `MAP cannot be greater than MSRP` | Yes |
    | `Price is below MAP (minimum advertised price)` | No |
    | `Price is above MSRP` | No |
    | `Your cost is above MAP` | No |
    | `Your cost is above MSRP` | No |

    The detail behind price warnings is capped per import. Past the cap the whole file gets one warning reading `Not every price advisory is listed: the detail is capped per import. Fix the listed ones and re-import to see the rest.` A very messy file therefore needs two passes.

    One more warning can arrive on a product you sell through the Repricer: `The price was saved in the PIM, but prices for this channel account are managed by the Repricer, so the imported values will not be published there.` Manage those prices from the Repricer, or undo the pairing to make the PIM's prices the ones that go out.
  </Accordion>

  <Accordion title="Errors about deleting">
    | Message | What to change |
    | --- | --- |
    | `Cannot delete: this row still has products assigned to it. Remove the assignments first.` | Reassign those products, or merge the record as [brands](/pim/catalog/brands) describes |
    | `Cannot delete: this category still has child categories. Delete the children first.` | Work up from the leaves |
    | `Cannot delete: this spec group still has spec definitions. Delete the definitions first.` | The same, one level down |
    | `Cannot delete: this spec definition still has spec values. Delete the values first.` | The same again |
    | `A category cannot be its own parent.` | Check the path in that row |
    | `Cannot move a category into one of its own descendants. This would create a cycle.` | Pick a parent outside the branch you are moving |
  </Accordion>
</AccordionGroup>

### Fixing a file and importing again

Download the Results file, fix your source file, and import again.

<Tip>
  The rows that already went in are the problem on your second attempt. Under `Create` they come back as duplicate errors, one per row that succeeded the first time.
</Tip>

So either cut those rows out of the file, or switch the import to `Update`, which rewrites them and leaves everything you did not map alone. `Update` is usually the faster of the two, because you do not have to work out which rows made it.

Images downloaded before a product was rejected stay in your library. Your next attempt finds and reuses them, so retrying a products file does not fill your library with duplicates.

## Where to go next

<Columns cols={2}>
  <Card title="Exports" icon="download" href="/pim/uploads/exports">
    The file shaped the way an import expects, and the round trip built on it.
  </Card>

  <Card title="Data sources" icon="rss" href="/pim/uploads/data-sources">
    The same file arriving on a schedule, and what it does differently.
  </Card>

  <Card title="Products" icon="package" href="/pim/catalog/products">
    What a row becomes, and the fields a products file writes into.
  </Card>

  <Card title="Assets" icon="images" href="/pim/assets">
    Where an imported image goes, and the limits its download has to clear.
  </Card>
</Columns>
