Skip to content

Improve CLI sync error messages for sites that can't be synced - #4202

Merged
gcsecsey merged 6 commits into
trunkfrom
gcsecsey/improve-plan-error-messages
Jul 16, 2026
Merged

Improve CLI sync error messages for sites that can't be synced#4202
gcsecsey merged 6 commits into
trunkfrom
gcsecsey/improve-plan-error-messages

Conversation

@gcsecsey

@gcsecsey gcsecsey commented Jul 15, 2026

Copy link
Copy Markdown
Member

Related issues

How AI was used in this PR

I used Claude to investigate the issue, trace the pull-reprint, push, and legacy pull flows, write the changes and tests. I reviewed and validated the messaging and the logic myself.

Proposed Changes

Trying to sync a Business-plan site that hasn't been Atomic transferred yet (or a Free/Personal site) failed with a misleading "This URL is not a WordPress.com or Pressable site connected to your account", even for sites you own. The root cause is that WordPress.com only returns options.software_version for Atomic/Jetpack sites, but the shared /me/sites schema marked it required, so every Simple site failed validation and was silently dropped from the list before it could be classified. Because those sites never appeared, the reprint pull couldn't resolve them and the sync UI couldn't show their real status.

This PR:

  • Makes software_version optional so Simple sites are retained and correctly classified as needs-transfer or needs-upgrade. This also repairs the Desktop sync list, which drops sites through the same schema
  • Centralizes per-state messaging so every CLI sync command names the actual condition and the next step (enable hosting features, upgrade the plan, etc) with the relevant WordPress.com link
  • Routes pull-reprint through that helper, and stops the picker from surfacing a raw internal state identifier for disabled sites

Testing Instructions

  • Build the CLI: npm run cli:build
  • With a Business-plan site that has not been transferred to Atomic, run STUDIO_ENABLE_PULL_REPRINT=true node apps/cli/dist/cli/main.mjs pull-reprint --path <local-site> --url <site-url>
  • Check that the error names hosting features and links to wordpress.com/hosting-features/<id>.
  • With a Free or Personal plan site, repeat and confirm the message asks to upgrade to a Business plan and links to wordpress.com/plans/<id>.
  • Run the existing studio push or studio pull commands with a mix of sites and confirm the Simple sites now appear as non-syncable entries in the picker with a readable reason (e.g. Transfer required, Plan upgrade required).
Scenario Before After
Business plan, pre-Atomic-transfer (needs-transfer) CleanShot 2026-07-15 at 12 07 35@2x CleanShot 2026-07-15 at 12 04 30@2x
Free or Personal plan (needs-upgrade) CleanShot 2026-07-15 at 12 08 33@2x CleanShot 2026-07-15 at 12 04 55@2x
push/pull picker listing a Simple site with its reason CleanShot 2026-07-15 at 12 09 20@2x CleanShot 2026-07-15 at 12 05 26@2x

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?
gcsecsey added 2 commits July 15, 2026 10:55
Report the specific syncSupport condition and next step (enable hosting features, upgrade plan, etc.) instead of a generic failure or a raw internal state identifier, including in the pull-reprint flow for Business-plan sites awaiting Atomic transfer.
… leak

Simplify the lone-non-syncable check in resolveSourceSite (nonSyncable is provably the whole list there), and give getSyncSupportLabel an already-connected case plus a non-leaking default so the picker no longer shows a raw state identifier.
software_version is only returned for Atomic/Jetpack sites, but the /me/sites schema required it, so every Simple site (Business plans awaiting Atomic transfer, plus Free/Personal plans) failed validation and was silently dropped. They never appeared in the list, so pull-reprint --url reported them as not connected and the sync UI could not surface their needs-transfer/needs-upgrade guidance. Make the field optional.
@gcsecsey
gcsecsey marked this pull request as ready for review July 15, 2026 11:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes sync site classification for WordPress.com “Simple” sites (e.g., Business sites not yet Atomic-transferred, plus Free/Personal plans) by relaxing the /me/sites response schema so these sites aren’t dropped during validation, and it improves CLI sync-related error messaging by centralizing per-state, actionable errors (including links for next steps).

Changes:

  • Make options.software_version optional in the shared /me/sites Zod schema so Simple sites are retained and can be classified.
  • Add coverage ensuring Simple sites are preserved and that wpVersion is undefined when the API omits software_version.
  • Centralize CLI non-syncable-site messaging via getSyncSupportError() and use it in pull-reprint (including the “only one site and it’s not pullable” case), plus improve picker labels.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/common/types/sync.ts Makes options.software_version optional so Simple sites don’t fail schema parsing.
packages/common/lib/sync/tests/transform-sites.test.ts Adds tests to ensure Simple sites are retained and wpVersion behavior matches API omission/presence.
apps/cli/lib/sync-site-picker.ts Introduces getSyncSupportError() and improves disabled-site labels to avoid surfacing raw internal states.
apps/cli/commands/tests/pull-reprint.test.ts Updates/adds assertions to validate the new per-state error messages in pull-reprint source resolution.
apps/cli/commands/pull-reprint.ts Routes non-syncable cases through the centralized error helper and improves the “no pullable sites” messaging for single-site accounts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@wpmobilebot

wpmobilebot commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing 1b86324 vs trunk

app-size

Metric trunk 1b86324 Diff Change
App Size (Mac) 1352.96 MB 1350.70 MB 2.26 MB 🟢 -0.2%

site-editor

Metric trunk 1b86324 Diff Change
load 1074 ms 1102 ms +28 ms ⚪ 0.0%

site-startup

Metric trunk 1b86324 Diff Change
siteCreation 6497 ms 6507 ms +10 ms ⚪ 0.0%
siteStartup 2395 ms 2391 ms 4 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@epeicher epeicher left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @gcsecsey for solving this! I have reviewed the code, and it looks good to me, but I have added a couple of questions about the wording of the messages and the list of sites to be returned.

Comment thread apps/cli/lib/sync-site-picker.ts Outdated
Comment on lines +27 to +31
// WordPress.com only returns software_version for Atomic/Jetpack
// sites; Simple sites (e.g. Business plans not yet transferred to
// Atomic, or Free/Personal plans) omit it. Requiring it here would
// silently drop every Simple site from the synced-sites list.
software_version: z.string().optional(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list of sites returned should match the existing list returned by the pull command, so we can mimic that functionality. I think simple sites are not returned now as they are not supported, so I'd say that it's fine not to return them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point on keeping feature parity, but I think this change preserves it. The change is in the shared fetchSyncableSites, so pull, push, pull-reprint and the Desktop all stay consistent.

Earlier, simple sites weren’t deliberately filtered out, it was a schema bug. options.software_version was marked required, but WordPress.com only returns it for Atomic/Jetpack sites, so every Simple site failed validation and was dropped.

IMO keeping them in the list is a small UX enhancement. Rather than hiding a site the customer paid for, we surface it as non-syncable with a suggested next step (“enable hosting features” / “upgrade your plan”).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds like a great improvement to me, if the next step is clear to the user. Thanks for improving this!

Comment thread apps/cli/lib/sync-site-picker.ts Outdated

@gavande1 gavande1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for improving the error messages. I tested this and it works as described. LGTM 🚀

There are a few comments on the wording, but approving to unblock you.

gcsecsey and others added 2 commits July 16, 2026 14:42
Co-authored-by: Rahul Gavande <rahul.gavande@automattic.com>
… a specific plan

Syncability depends on the plan including hosting features (wp-cloud), not on the Business plan specifically, so the needs-upgrade message no longer names a plan tier.

@epeicher epeicher left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for improving this @gcsecsey! The new messages have the URL indicating the user how to proceed. Changes LGTM!

Comment thread apps/cli/lib/sync-site-picker.ts
@gcsecsey
gcsecsey merged commit 247329a into trunk Jul 16, 2026
18 checks passed
@gcsecsey
gcsecsey deleted the gcsecsey/improve-plan-error-messages branch July 16, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

5 participants