Troubleshooting#
Each entry is a message the plugin prints, what causes it and what to do. Messages are quoted from the code. On the
command line they appear after Error:; in the admin screen, in red under the progress bar.
Connection and signature#
Missing signature#
Missing signature.
Cause. The receiver did not get a well-formed X-BB-Migrate-Signature header. Either something between the two
sites removed the header, or the request did not come from BB Migrate.
Fix. Check that a proxy, firewall or security plugin does not strip unknown request headers. Test from the sender with Test connection.
Signature expired#
Signature expired; check both clocks.
Cause. The timestamp in the signature is more than 300 seconds from the receiver's clock. One of the two servers has the wrong time.
Fix. Compare date -u on both servers and fix time synchronisation (NTP) on the one that is off.
Bad signature#
Bad signature: the connection key does not match (or the clocks/route differ).
Cause. The HMAC does not verify. Usual reasons:
- the key in the connection string is not the receiver's current key (it was regenerated, it belongs to another site, or it was truncated when it was copied);
- the connection string's URL reaches a different site than the one whose key you pasted;
- something rewrote the request body in transit, so the body the receiver hashed is not the one the sender signed.
Fix. Copy the connection string again from the receiver (wp bb-migrate key there, or its Settings tab), as one
quoted argument. If the key is right, look for a proxy that alters request bodies.
Replayed request#
Replayed request.
Cause. The receiver could not create the marker file for this signature. Either the exact same signed request
was delivered twice (a proxy that retries a POST, for example), or the folder wp-content/uploads/bb-migrate/nonces/
on the receiver is not writable, in which case every request fails this way.
Fix. If every request fails, fix ownership or permissions of the receiver's uploads/bb-migrate/ folder so PHP
can write to it. If it happens occasionally, the first delivery of the request usually succeeded: check the result
before repeating the operation.
Connection string does not parse#
Connection info must be "<url> <key>" as shown on the other site's BB Migrate settings page.
Connection must be "<url> <key>".
Cause. The connection string did not parse. Besides a missing key or a missing space, this is what an http://
URL to a host that does not look local produces: plain HTTP is accepted only for loopback, private ranges,
single-label names and .local, .test, .localhost, .internal, .lan.
Fix. Quote the whole string as one argument. Use https:// for anything that is not a local host.
Unexpected HTML response#
Unexpected response (404) from handshake: (an HTML page, not the plugin: wrong URL, a firewall, or the plugin is inactive there)
Cause. The reply was not JSON. The status code narrows it down:
| Status | Likely cause |
|---|---|
| 404 | The URL is wrong, the plugin is not active on the remote, or the site has no pretty permalinks |
| 301, 302 | The URL redirects (http → https, www → bare domain). The client does not follow redirects |
| 401, 403 | HTTP authentication, a firewall, a WAF challenge or a security plugin in front of the REST API |
| 413 | A proxy or web server rejected the body as too large |
| 500, 502, 503 | A PHP fatal on the remote, or the server is down. See the remote's PHP error log |
| 520, 524 | The CDN lost the origin or stopped waiting for it. See Hosting notes |
Fix. Use the connection string exactly as the remote prints it, including the scheme and host it uses for its
own home URL. For a site without pretty permalinks use the ?rest_route=/bb-migrate/v1 form. Open
https://<remote>/wp-json/bb-migrate/v1 in a browser: a JSON document that lists the routes means the plugin is
reachable.
Request failed#
Request failed: cURL error 28: Operation timed out …
Request failed: cURL error 56: … SSL read …
Cause. The HTTP request itself failed: DNS, TLS, a dropped connection or a timeout. Idempotent routes are retried up to three times before this is reported.
Fix. For certificate errors between local containers, turn off "Verify SSL certificates" on the sending site. For read errors during uploads, lower "Max request size" on the sending site. For a timeout on an import, see Hosting notes. A message that says a valid URL was not provided means the target is a private or loopback address and the sending site is not local.
Version mismatch warning#
WARNING: Remote runs BB Migrate 0.2.1, this site 0.2.2. Update both to the same version before transferring.
Cause. The handshake reported a different plugin version on the remote. It is a warning; the transfer continues.
Fix. Upload the same zip to both sites. If you just updated the remote and the warning persists for a minute, that is the remote's opcache: see Hosting notes. Routes or checks that exist only in the newer version will not work until both match.
Switches and scopes#
Switch off#
This site does not accept pushes. Enable "Accept push" in its BB Migrate settings.
This site does not allow pulls. Enable "Allow pull" in its BB Migrate settings.
This site does not allow theme/plugin file transfers. Enable "Allow code files" in its BB Migrate settings.
This site does not allow plugin changes. Enable "Allow code files" in its BB Migrate settings.
Cause. The switch the route needs is off on the remote. "This site" in the message is the remote.
Fix. On the remote: wp bb-migrate settings --allow-push=1 (or --allow-pull=1, --allow-code-files=1), or its
Settings tab. Two cases surprise people:
- A file push reports "does not allow pulls": the diff reads the remote's file listing, which is a read route. A file push needs Allow pull and Accept push.
site pluginsandsite cacheonly read, but are served by write routes: they need Accept push.
Unknown scope#
Unknown scope.
Cause. The scope is not one of uploads, themes, theme:<slug>, plugins, plugin:<slug>; the slug contains
characters other than letters, digits, _, -, .; or the scope is BB Migrate's own folder (plugin:bb-migrate),
which is never a scope.
Fix. Correct the scope. To update BB Migrate itself, upload its zip under Plugins → Add New.
Delete is only allowed…#
Delete is only allowed for theme/plugin scopes, or for uploads confined to named paths.
Cause. --delete with --scope=uploads and no --paths.
Fix. Add --paths to say which part of uploads the sync owns, or drop --delete.
Files#
Write refused#
The remote could not write 3 of 120 files (first: functions.php). Its folder for this scope is not writable by PHP there (ownership / permissions), or the path is refused.
Write refused for assets/video/intro.mp4: the path is outside the scope, a symlink, or the folder is not writable.
Cause. In order of likelihood:
- The folder on the remote belongs to another user than the one PHP runs as (uploaded over SFTP, deployed by another tool).
- The target or one of its parent folders is a symlink, or resolves outside the scope root.
- In the uploads scope, the file name is refused: an executable extension anywhere in the name, a server configuration file, or a dotfile.
Fix. For 1, fix ownership once: Hosting notes. For 2, deploy to the real folder rather than through a link. For 3, the refusal is intended.
Chunk arrived without a path or data#
Chunk arrived without a path or data: the request body was probably truncated by a proxy or firewall (N bytes received). Lower "Max request size" on the sending site.
Cause. The receiver got a body that no longer decoded to the expected fields. Something cut it.
Fix. Lower "Max request size (bytes)" on the sending site's Settings tab, for example to 131072, and run the sync again. Files already written are skipped.
A pull finished but files are missing#
Cause. A pull skips files this site cannot write and does not stop. Or the remote's max_request is lower than
this site's, so the remote left files out of a batch.
Fix. Check that PHP can write to the local scope folder. Set this site's "Max request size" no higher than the remote's. Run the pull again; it copies what still differs.
Files are copied again on every sync#
Cause. The comparison is by size and modification time, not by content. A build that rewrites its output gives every file a newer time, and a newer time on the source counts as a change even when the bytes are identical.
Fix. None needed for correctness. To cut the traffic, sync only the paths that changed with --paths.
Database#
This site is not local#
This site is not local. Re-run with --yes to overwrite https://example.com
Cause. import or pull on a site whose host does not look local. This is a guard against overwriting the
wrong database.
Fix. Check which site you are on. If it is the right one, add --yes.
A backup started here less than five minutes ago#
A backup started here less than five minutes ago; wait before pushing again.
Cause. The receiver starts at most one pre-push backup every five minutes.
Fix. Wait, or push with --skip-backup if the backup taken a moment ago is the one you want to keep.
Refused statement from remote#
Refused statement from remote: …
Cause. A statement in pushed or pulled SQL is not one of the forms on the
allow-list. Between two sites running the same plugin version this
should not happen with ordinary tables. Candidates: a version mismatch, or a table whose CREATE TABLE statement
uses a feature the list excludes (a UNION or FEDERATED engine definition, a DATA DIRECTORY clause, table
encryption or tablespace options, a comment or @ outside a quoted string).
Fix. Update both sites to the same version. If one table is the cause, leave it out with --tables and move it
another way. The message carries the first 80 characters of the refused statement, which names the table.
Corrupt or oversized chunk#
Corrupt or oversized chunk.
Cause. A pushed SQL chunk did not decompress, or decompressed to more than the larger of 8 MB and four times the
receiver's max_request. Rows with very large values can do this.
Fix. Raise "Max request size" on the receiving site, or lower "Rows per step" on the sending site.
Nothing was imported#
Nothing was imported (no temp tables found).
Cause. The file or transfer contained no CREATE TABLE or INSERT for any table, so there is nothing to swap
in. For a file: it is empty, or not a SQL dump.
Fix. Inspect the file: gunzip -c file.sql.gz | head.
MySQL error…#
MySQL error 1153: Got a packet bigger than 'max_allowed_packet' bytes
Cause. The database server rejected a statement. The exporter keeps each INSERT under about 1 MB, but a single
row can be larger than the server's max_allowed_packet.
Fix. Raise max_allowed_packet on the destination's database server.
Page packages and snippets#
Snippet not printing after a push#
A Custom CSS & JS snippet was pushed and the site does not show it. Check in this order:
| Check | Why | Fix |
|---|---|---|
Was it imported as private or draft? |
Only published snippets get a file. The import warns Some snippets were not regenerated… |
Push with --status=keep, or --on-exists=update --status=keep for an existing snippet |
| Was it skipped? | Snippet <slug> skipped: its options are not a css/js/html snippet… means the options failed validation |
Fix the snippet's language or preprocessor settings at the source |
| Did it arrive by a database push? | The snippet plugin writes its served files only from its own edit screen | wp bb-migrate site snippets "<connection>" |
| Does it have "where on site" rules? | The URL-rules index (custom-css-js-urls) must list it. Versions before the index rebuild left it out |
Update both sites to the current 0.2.2 build and run site snippets |
| Is it deactivated at the source? | The rebuilt search tree honours the snippet's active flag | Activate it at the source and push again |
| Is the snippet plugin the same version on both sites? | An older version on the receiver may not evaluate a rule type the newer one writes | Update the snippet plugin on the receiver |
| Is a cache serving the old page? | Regeneration fires bb_cache_purge_all and flushes the object cache; a CDN or another cache plugin may still hold the page |
Purge that cache |
site snippets fails with Custom CSS & JS is not active on this site. when the snippet plugin is inactive on the
remote.
Missing file for attachment#
WARNING: Missing file for attachment 812: 2026/10/poster.jpg
Cause. The package lists an attachment whose file is not in the destination's uploads when the import runs: the file transfer failed for it, the file is missing on the source, or its name is refused by the uploads rule.
Fix. Send the file (wp bb-migrate files push "<connection>" --scope=uploads --paths=2026/10/poster.jpg) and push
the page again with --on-exists=update.
An import behind a proxy ends with an error but some posts arrived#
Cause. The import ran in one request and the proxy stopped waiting (Cloudflare: 100 seconds).
Fix. List what arrived, then push the rest in smaller batches or straight to the origin. See Hosting notes.
Pushed content has > or lost its script tags#
Cause. The receiving site has no administrator to run the import as, so WordPress filtered the content as untrusted HTML. Imports run as the first administrator when the request has no user.
Fix. Make sure the remote has at least one user with the administrator role.
ZipArchive is not available on this server#
Cause. The PHP zip extension is missing; it is needed for package zips.
Fix. Install the extension, or use push and pull instead of a zip.
Site actions#
This action needs the full site…#
This action needs the full site, but the compatibility mu-plugin on this site is an old version: deactivate and reactivate BB Migrate there (or open its settings page) to refresh mu-plugins/bb-migrate-compat.php.
Cause. The remote's copy of the mu-plugin predates site actions and stripped the site for this request.
Fix. Open Tools → BB Migrate on the remote once, or run any wp bb-migrate command there. Check that PHP can
write to wp-content/mu-plugins/.
No page with slug … on this site#
No page with slug "home" on this site.
Cause. meta push found no post with the local post's slug and type on the remote.
Fix. Pass --type=<post_type> if the type differs, or push the page first.
BB Cache is not active#
BB Cache is not active on the remote.
BB Cache is not active on this site.
Cause. The cache actions call into the BB Cache plugin: on the remote for cache and cache-set, and on this
site as well for cache-copy.
Fix. Activate it: wp bb-migrate site activate "<connection>" bb-cache.
Collecting information#
When something fails and none of the above fits:
- Run Test connection (or any command) and note the exact message and status code.
- Read the job log; warnings are prefixed
WARNING:and the failing step is the last line beforeERROR:. - Look at the receiver's PHP error log. Import errors are logged there in full as
BB Migrate import-chunk: …orBB Migrate import-finalize: …. - Compare versions: Tools → BB Migrate shows the version next to the title on each site.
Never paste a connection string into a bug report.