From a311aa16e00944c37030d7c16ee3c7d987d33c24 Mon Sep 17 00:00:00 2001
From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com>
Date: Thu, 20 Aug 2026 02:02:05 +0000
Subject: [PATCH 1/5] docs: clarify partial transfer stage behavior and
preserve semantics
Add documentation explaining how --only and --exclude filters work with
data transfer stages (content, files, config). Clarifies that omitted
stages preserve destination data and documents the content-replace-keep-config
workflow with a stage transfer matrix.
Related to strapi/strapi#27322
---
.../cms/features/data-management/transfer.md | 52 ++++++++++++++++++-
1 file changed, 51 insertions(+), 1 deletion(-)
diff --git a/docusaurus/docs/cms/features/data-management/transfer.md b/docusaurus/docs/cms/features/data-management/transfer.md
index fb22c0655f..51997dc2b7 100644
--- a/docusaurus/docs/cms/features/data-management/transfer.md
+++ b/docusaurus/docs/cms/features/data-management/transfer.md
@@ -243,9 +243,59 @@ npm run strapi transfer -- --to https://example.com/admin --exclude files
:::warning
-Any types excluded from the transfer will be deleted in your destination instance. For example, if you exclude `config` the project configuration in your destination instance will be deleted.
+When using `--exclude` or `--only` to filter which stages (content, files, config) are transferred, the stages you omit will **not be deleted** on the destination instance. Their data is preserved. However, if you transfer a stage without filters, that stage is fully replaced on the destination.
:::
+## Understanding partial transfers and stage filtering
+
+When using `--only` or `--exclude` to transfer specific stages (content, files, config), the behavior differs based on whether you're filtering:
+
+- **Omitted stages are preserved**: When a stage is not transferred (either via `--only content` or `--exclude files`), the destination data for that stage is left untouched.
+- **Transferred stages are replaced**: Any stage you include in the transfer fully replaces the destination data for that stage.
+
+### Common workflows
+
+#### Content refresh while preserving destination config
+
+To refresh only content from a source instance while keeping the destination instance's configuration:
+
+
+
+
+
+```bash
+yarn strapi transfer --to https://example.com/admin --to-token my-transfer-token --only content
+```
+
+
+
+
+
+```bash
+npm run strapi transfer -- --to https://example.com/admin --to-token my-transfer-token --only content
+```
+
+
+
+
+
+In this workflow, the destination configuration is preserved while content is updated from the source.
+
+### Stage transfer behavior matrix
+
+| Scenario | Content transferred? | Files transferred? | Config transferred? | Destination untouched |
+|----------|:--------------------:|:------------------:|:-------------------:|:---------------------:|
+| Default `strapi transfer` | ✓ | ✓ | ✓ | None |
+| `--only content` | ✓ | ✗ | ✗ | Files, Config |
+| `--only files` | ✗ | ✓ | ✗ | Content, Config |
+| `--only config` | ✗ | ✗ | ✓ | Content, Files |
+| `--only content,files` | ✓ | ✓ | ✗ | Config |
+| `--exclude content` | ✗ | ✓ | ✓ | Content |
+| `--exclude files` | ✓ | ✗ | ✓ | Files |
+| `--exclude config` | ✓ | ✓ | ✗ | Config |
+
+When a stage is omitted (shown as ✗ in the "transferred" columns or listed under "Destination untouched"), the destination instance retains its existing data for that stage.
+
## Filter content types during transfer
From 9df6d79514886feabeaa6a9bb6c4490df5900947 Mon Sep 17 00:00:00 2001
From: Pierre Wizla <4233866+pwizla@users.noreply.github.com>
Date: Fri, 21 Aug 2026 17:17:51 +0200
Subject: [PATCH 2/5] Fix stage transfer behavior matrix and partial transfer
semantics
The matrix contradicted the upstream engine matrix in strapi/strapi#27322 on
--exclude files, omitted the --exclude media-library row, and claimed nothing is
preserved by default. Media library records travel with content, so excluding
files leaves records pointing at untransferred binaries. Also corrects the two
quoted CLI prompts to match command.ts and scopes the --force caution to the
stages actually transferred.
---
.../cms/features/data-management/transfer.md | 71 +++++++++++--------
1 file changed, 40 insertions(+), 31 deletions(-)
diff --git a/docusaurus/docs/cms/features/data-management/transfer.md b/docusaurus/docs/cms/features/data-management/transfer.md
index 51997dc2b7..e250ffcc62 100644
--- a/docusaurus/docs/cms/features/data-management/transfer.md
+++ b/docusaurus/docs/cms/features/data-management/transfer.md
@@ -41,15 +41,15 @@ The CLI command consists of the following arguments:
| Option | Description |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `--to` | Full URL of the `/admin` endpoint on the destination Strapi instance
(e.g. `--to https://my-beautiful-strapi-website/admin`) |
-| `‑‑to‑token` | Transfer token from the Strapi destination instance. |
+| `--to-token` | Transfer token from the Strapi destination instance. |
| `--from` | Full URL of the `/admin` endpoint of the remote Strapi instance to pull data from (e.g., `--from https://my-beautiful-strapi-website/admin`) |
-| `‑‑from‑token` | Transfer token from the Strapi source instance. |
+| `--from-token` | Transfer token from the Strapi source instance. |
| `--force` | Automatically answer "yes" to all prompts, including potentially destructive requests, and run non-interactively. |
| `--exclude` | Exclude data using comma-separated data types. The available types are: `content`, `files`, `config`, and `media-library` (excludes both upload binaries and upload content type records). |
| `--only` | Include only these data. The available types are: `content`, `files`, and `config`. |
| `--exclude-content-types` | Comma-separated list of content-type UIDs to exclude. Both entity records and relation links touching an excluded type are skipped. |
| `--only-content-types` | Comma-separated list of content-type UIDs to include. Only entity records and relation links for the listed types are transferred. |
-| `--throttle` | Time in milliseconds to inject an artificial delay between the "chunks" during a transfer. |
+| `--throttle` | Time in milliseconds to inject an artificial delay between each transferred entity. |
| `--no-checksums` | Disable end-to-end SHA-256 checksum verification for assets. Checksum verification is enabled by default when both the source and destination instances support it. |
| `--verbose` | Enable verbose logs. |
@@ -122,7 +122,7 @@ Initiating a data transfer depends on whether you want to push data to a remote
4. Add the transfer token when prompted to do so.
- 5. Answer **Yes** or **No** to the CLI prompt: "The transfer will delete all of the remote Strapi assets and its database. Are you sure you want to proceed?"
+ 5. Answer **Yes** or **No** to the CLI prompt: "The transfer will delete existing data from the remote Strapi! Are you sure you want to proceed?"
@@ -153,7 +153,7 @@ Initiating a data transfer depends on whether you want to push data to a remote
4. Add the transfer token when prompted to do so.
-5. Answer **Yes** or **No** to the CLI prompt: "The transfer will delete all of the local Strapi assets and its database. Are you sure you want to proceed?".
+5. Answer **Yes** or **No** to the CLI prompt: "The transfer will delete all the local Strapi assets and its database. Are you sure you want to proceed?".
@@ -162,10 +162,10 @@ Once the transfer starts, the command reports live progress in the terminal, inc
## Bypass all `transfer` command line prompts
-When using the `strapi transfer` command, you are required to confirm that the transfer will delete the existing database contents. The `--force` flag allows you to bypass this prompt. This option is useful for implementing `strapi transfer` programmatically. You must pass the `to-token` option with the transfer token if you use the `--force` option.
+When using the `strapi transfer` command, you are required to confirm that the transfer will delete the existing database contents. The `--force` flag allows you to bypass this prompt. This option is useful for implementing `strapi transfer` programmatically. You must pass the `--to-token` option with the transfer token if you use the `--force` option.
:::caution
-The `--force` option bypasses all warnings about content deletion.
+The `--force` option bypasses all warnings about content deletion. The deletion only covers the stages that are actually transferred: if you filter stages with `--only` or `--exclude`, the omitted stages are preserved. See [Understanding partial transfers and stage filtering](#understanding-partial-transfers-and-stage-filtering).
:::
### Example: bypass the `transfer` command line prompts with `--force`
@@ -242,20 +242,16 @@ npm run strapi transfer -- --to https://example.com/admin --exclude files
-:::warning
-When using `--exclude` or `--only` to filter which stages (content, files, config) are transferred, the stages you omit will **not be deleted** on the destination instance. Their data is preserved. However, if you transfer a stage without filters, that stage is fully replaced on the destination.
-:::
-
## Understanding partial transfers and stage filtering
-When using `--only` or `--exclude` to transfer specific stages (content, files, config), the behavior differs based on whether you're filtering:
+When you use `--only` or `--exclude`, only the stages you name are affected on the destination:
-- **Omitted stages are preserved**: When a stage is not transferred (either via `--only content` or `--exclude files`), the destination data for that stage is left untouched.
-- **Transferred stages are replaced**: Any stage you include in the transfer fully replaces the destination data for that stage.
+- **Omitted stages are preserved.** When a stage is not transferred, the destination data for that stage is left untouched.
+- **Transferred stages are replaced.** Any stage you include in the transfer fully replaces the destination data for that stage.
-### Common workflows
+Stage filtering and content-type filtering are independent and can be combined. Stage filters (`--only` and `--exclude`) select which kinds of data move. Content-type filters (`--only-content-types` and `--exclude-content-types`) narrow which content types move within the content stage.
-#### Content refresh while preserving destination config
+### Example: refresh content while preserving destination config
To refresh only content from a source instance while keeping the destination instance's configuration:
@@ -279,22 +275,35 @@ npm run strapi transfer -- --to https://example.com/admin --to-token my-transfer
-In this workflow, the destination configuration is preserved while content is updated from the source.
+### Stage transfer behavior
+
+Each stage preset covers a specific payload:
-### Stage transfer behavior matrix
+| Preset | Stages | Payload |
+|--------|--------|---------|
+| `content` | entities, links | Content-type rows, including media library database records, and relations |
+| `files` | assets | Upload binaries under `public/uploads` |
+| `config` | configuration | Core store and webhooks |
-| Scenario | Content transferred? | Files transferred? | Config transferred? | Destination untouched |
-|----------|:--------------------:|:------------------:|:-------------------:|:---------------------:|
-| Default `strapi transfer` | ✓ | ✓ | ✓ | None |
-| `--only content` | ✓ | ✗ | ✗ | Files, Config |
-| `--only files` | ✗ | ✓ | ✗ | Content, Config |
-| `--only config` | ✗ | ✗ | ✓ | Content, Files |
-| `--only content,files` | ✓ | ✓ | ✗ | Config |
-| `--exclude content` | ✗ | ✓ | ✓ | Content |
-| `--exclude files` | ✓ | ✗ | ✓ | Files |
-| `--exclude config` | ✓ | ✓ | ✗ | Config |
+Schemas are always transferred, independently of these presets.
+
+| Flags | Transferred | Preserved on the destination |
+|-------|-------------|------------------------------|
+| Default `strapi transfer` | Content, files, config | Admin and ignored types only |
+| `--only content` | Content | Config and upload binaries |
+| `--only files` | Files | Content and config |
+| `--only config` | Config | Content and files |
+| `--only content,files` | Content and files | Config |
+| `--exclude content` | Files and config | Content |
+| `--exclude files` | Content and config | Upload binaries |
+| `--exclude config` | Content and files | Config |
+| `--exclude media-library` | Content without upload types, and config | Upload binaries, `plugin::upload.file`, and `plugin::upload.folder` |
+
+:::caution
+The `files` preset covers only the binaries under `public/uploads`. Media library database records (`plugin::upload.file` and `plugin::upload.folder`) are part of the `content` preset. This means `--exclude files` alone only skips the assets stage: the media library records still transfer with the rest of the content, so the destination can end up with records pointing to binaries that were never transferred. To preserve both the binaries and their records, use `--exclude media-library`.
+:::
-When a stage is omitted (shown as ✗ in the "transferred" columns or listed under "Destination untouched"), the destination instance retains its existing data for that stage.
+Content is never wiped entirely: admin types and ignored types, such as `plugin::content-releases.release`, are always preserved on the destination.
## Filter content types during transfer
@@ -303,7 +312,7 @@ When a stage is omitted (shown as ✗ in the "transferred" columns or listed und
The `--exclude-content-types` and `--only-content-types` options let you scope a transfer to specific content types. Both options accept a comma-separated list of content-type UIDs (for example, `api::article.article`). Unknown UIDs are validated against the Strapi schema at startup. Both entity records and any relation links touching an excluded type are skipped automatically.
:::warning Warning: Restore behavior
-- When you use `--exclude-content-types`, data for the excluded types is **preserved** on the destination — they are not wiped before the transfer.
+- When you use `--exclude-content-types`, data for the excluded types is **preserved** on the destination: they are not wiped before the transfer.
- When you use `--only-content-types`, the pre-transfer wipe is scoped to only the listed UIDs, leaving all other content on the destination in place.
:::
@@ -357,7 +366,7 @@ npm run strapi transfer -- --to https://example.com/admin --to-token my-transfer
## Manage data transfer with environment variables
-The environment variable `STRAPI_DISABLE_REMOTE_DATA_TRANSFER` is available to disable remote data transfer. In addition to the [RBAC permissions](/cms/features/rbac#plugins-and-settings) in the admin panel this can help you secure your Strapi application. To use `STRAPI_DISABLE_REMOTE_DATA_TRANSFER` you can add it to your `.env` file or preface the `start` script. See the following example:
+The environment variable `STRAPI_DISABLE_REMOTE_DATA_TRANSFER` is available to disable remote data transfer. In addition to the [RBAC permissions](/cms/features/rbac#configuring-roles-permissions) in the admin panel this can help you secure your Strapi application. To use `STRAPI_DISABLE_REMOTE_DATA_TRANSFER` you can add it to your `.env` file or preface the `start` script. See the following example:
```bash
STRAPI_DISABLE_REMOTE_DATA_TRANSFER=true yarn start
From b1c0e23cc40e020f5764218903a49b308897e927 Mon Sep 17 00:00:00 2001
From: Pierre Wizla <4233866+pwizla@users.noreply.github.com>
Date: Fri, 21 Aug 2026 17:17:58 +0200
Subject: [PATCH 3/5] Fix contradictory excluded-stage deletion warning in
import page
The warning claimed excluded types are deleted in the target instance, the
opposite of the transfer page. Verified that import and transfer share the same
parseRestoreFromOptions call, so the semantics are identical: omitted stages are
preserved.
---
docusaurus/docs/cms/features/data-management/import.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docusaurus/docs/cms/features/data-management/import.md b/docusaurus/docs/cms/features/data-management/import.md
index e1f38e7979..9663207c20 100644
--- a/docusaurus/docs/cms/features/data-management/import.md
+++ b/docusaurus/docs/cms/features/data-management/import.md
@@ -219,7 +219,7 @@ npm run strapi import -- -f /path/to/my/file/export_20221213105643.tar.gz.enc --
The default `strapi import` command imports your content (entities and relations), files (assets), project configuration, and schemas. The `--exclude` option allows you to exclude content, files, and the project configuration by passing these items in a comma-separated string with no spaces between the types. You can't exclude the schemas, as schema matching is used for `strapi import`.
:::warning
-Any types excluded from the import will be deleted in your target instance. For example, if you exclude `config` the project configuration in your target instance will be deleted.
+Stages omitted with `--exclude` or `--only` are not wiped in your target instance: their existing data is preserved. For example, if you exclude `config`, the project configuration already present in your target instance is left untouched. Stages that are imported fully replace the corresponding data in the target instance.
:::
:::note
From a21ae17c82fc0d0c2af74033a4176e38a4a7cf9f Mon Sep 17 00:00:00 2001
From: Pierre Wizla <4233866+pwizla@users.noreply.github.com>
Date: Fri, 21 Aug 2026 17:18:05 +0200
Subject: [PATCH 4/5] Sync transfer option table in CLI reference with the
transfer page
Adds the --throttle, --no-checksums and --verbose rows that were missing from
the strapi transfer table, and harmonizes the --exclude-content-types wording
across the export, import and transfer tables.
---
docusaurus/docs/cms/cli.md | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/docusaurus/docs/cms/cli.md b/docusaurus/docs/cms/cli.md
index 9ba57ae1c1..6bc5dd28ad 100644
--- a/docusaurus/docs/cms/cli.md
+++ b/docusaurus/docs/cms/cli.md
@@ -229,7 +229,7 @@ The exported file is automatically named using the format `export_YYYYMMDDHHMMSS
| `--format` | string | Export format: `tar` (default) or `dir`. Directory exports require `--no-encrypt`. |
| `--exclude` | string | Exclude data using comma-separated data types. The available types are: `content`, `files`, `config`, and `media-library` (excludes both upload binaries and upload content type records). |
| `--only` | string | Include only these data. The available types are: `content`, `files`, and `config`. |
-| `--exclude-content-types` | string | Comma-separated list of content-type UIDs to exclude from the export. Both entity records and relation links are excluded. |
+| `--exclude-content-types` | string | Comma-separated list of content-type UIDs to exclude from the export. Both entity records and relation links touching an excluded type are skipped. |
| `--only-content-types` | string | Comma-separated list of content-type UIDs to include in the export. |
| `-h`,
`--help` | - | Displays help for the `strapi export` command. |
@@ -267,7 +267,7 @@ The command accepts archives generated by `strapi export` (`.tar`, `.tar.gz`, `.
| -------------- | ------ | ------------------------------------------------------------------------------------- |
| `-k,` `--key` | string | Provide the encryption key in the command instead of a subsequent prompt. |
| `-f`, `--file` | string | Path to a `.tar[.gz][.enc]` archive or to an unpacked export directory. |
-| `--exclude-content-types` | string | Comma-separated list of content-type UIDs to exclude from the import. Excluded types are preserved on the destination. |
+| `--exclude-content-types` | string | Comma-separated list of content-type UIDs to exclude from the import. Both entity records and relation links touching an excluded type are skipped, and the excluded types are preserved on the destination. |
| `--only-content-types` | string | Comma-separated list of content-type UIDs to include in the import. |
| `-h`, `--help` | - | Display the `strapi import` help commands. |
@@ -298,12 +298,15 @@ The destination Strapi instance should be running with the `start` command and n
| `--to [destinationURL]` | Full URL of the `/admin` endpoint on the destination Strapi instance
(e.g. `--to https://my-beautiful-strapi-website/admin`) |
| `--to-token [transferToken]` | Transfer token for the remote Strapi destination |
| `--from [sourceURL]` | Full URL of the `/admin` endpoint of the remote Strapi instance to pull data from
(e.g., `--from https://my-beautiful-strapi-website/admin`) |
-| `‑‑from‑token` | Transfer token from the Strapi source instance. |
+| `--from-token` | Transfer token from the Strapi source instance. |
| `--force` | Automatically answer "yes" to all prompts, including potentially destructive requests, and run non-interactively. |
| `--exclude` | Exclude data using comma-separated data types. The available types are: `content`, `files`, `config`, and `media-library` (excludes both upload binaries and upload content type records). |
| `--only` | Include only these data. The available types are: `content`, `files`, and `config`. |
-| `--exclude-content-types` | Comma-separated list of content-type UIDs to exclude. Both entity records and relation links are excluded. |
+| `--exclude-content-types` | Comma-separated list of content-type UIDs to exclude. Both entity records and relation links touching an excluded type are skipped. |
| `--only-content-types` | Comma-separated list of content-type UIDs to include. Only entity records and relation links for the listed types are transferred. |
+| `--throttle` | Time in milliseconds to inject an artificial delay between each transferred entity. |
+| `--no-checksums` | Disable end-to-end SHA-256 checksum verification for assets. Checksum verification is enabled by default when both the source and destination instances support it. |
+| `--verbose` | Enable verbose logs. |
| `-h`, `--help` | Displays the commands for `strapi transfer`. |
:::caution
From 17dab68e1ff45dbd85440016a38c3a46455ddbc1 Mon Sep 17 00:00:00 2001
From: Pierre Wizla <4233866+pwizla@users.noreply.github.com>
Date: Fri, 21 Aug 2026 17:22:47 +0200
Subject: [PATCH 5/5] Add data transfer stage filtering pitfalls to the
known-pitfalls catalog
Four entries derived from the review of this PR, each verified against
parseRestoreFromOptions, TransferGroupPresets and expandMediaLibraryPreset:
the files preset covers binaries only while media library records ride the
content stage, the default command always preserves admin and ignored types,
omitted stages are preserved rather than deleted across import and transfer,
and the quoted CLI confirmation prompts must be checked against command.ts.
---
.../references/prompts/integrity-known-pitfalls.md | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md b/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md
index 78939614a4..150719fdd3 100644
--- a/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md
+++ b/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md
@@ -40,6 +40,17 @@ This file lists documented patterns where AI-generated documentation has produce
| `const { primitives } = require('@strapi/utils')` | `const { strings, objects, arrays, dates } = require('@strapi/utils')` | `@strapi/utils` does `export * from './primitives'` (flattened), not `export * as primitives` |
| `validateYupSchema` under the `yup` namespace | `validateYupSchema` is a top-level export from `@strapi/utils` | Exported from `./validators`, not from `./yup`. Import as `const { validateYupSchema } = require('@strapi/utils')`. |
+### Data transfer stage filtering
+
+Verified against `packages/core/strapi/src/cli/utils/data-transfer.ts` (`parseRestoreFromOptions`, `expandMediaLibraryPreset`), `packages/core/data-transfer/src/engine/index.ts` (`TransferGroupPresets`), and `packages/core/data-transfer/src/strapi/providers/local-destination/strategies/restore/index.ts` (`deleteEntitiesRecords`).
+
+| Hallucinated pattern | Correct pattern | Context |
+|---------------------|-----------------|---------|
+| `--exclude files` (or `--only content`) described as preserving "files" or "the media library" on the destination | It preserves only the **binaries** under `public/uploads`. Media library DB records (`plugin::upload.file`, `plugin::upload.folder`) are part of the `content` preset and still transfer. Only `--exclude media-library` preserves both. | `TransferGroupPresets.files` is `{assets: true}` only; upload records ride the `entities` stage with `content`. Data-loss-adjacent: the wrong claim leaves the destination with records pointing at binaries that were never transferred. Always state which of the two halves is preserved, never just "files". |
+| A stage-filtering matrix whose default-command row claims nothing is preserved on the destination | The default command always preserves `admin::*` types and `IGNORED_CONTENT_TYPES` (`plugin::content-releases.release`, `…release-action`) | `entitiesOptions.exclude` unconditionally contains the admin-prefixed and ignored types, so content is never wiped entirely. A "None preserved" row is always wrong. |
+| `--exclude` / `--only` described as **deleting** the omitted types on the target instance (any data-management page) | Omitted stages are **preserved**; only transferred stages are replaced | `strapi import` and `strapi transfer` both call the same `parseRestoreFromOptions`, so the semantics are identical across the two pages. When a stage is out of scope, `entities.include` is set to `[]`, which matches nothing and short-circuits deletion. Check `import.md`, `export.md`, `transfer.md`, and `cli.md` agree: they have contradicted each other before. |
+| A docs page quoting a `strapi transfer` confirmation prompt as "will delete all of the remote Strapi assets and its database" | The remote prompt is "The transfer will delete existing data from the remote Strapi!"; the local one is "…delete all **the** local Strapi assets and its database" | Reworded upstream precisely because `--only`/`--exclude` mean a transfer no longer always deletes everything. Verify quoted prompt strings against `packages/core/strapi/src/cli/commands/transfer/command.ts` rather than copying older docs. |
+
### Documentation formatting conventions
These are not code hallucinations but recurring Strapi-docs formatting mistakes. Verified against `STYLE_GUIDE.pdf` and `docusaurus/src/components/Icon.js`.