BigPizzaV3/CodexPlusPlus · error · anyhow::Error
provider sync did not complete
Error message
provider sync did not complete ({status:?}): {message} What it means
require_completed_provider_sync validates that a provider sync reached the terminal Synced state before the launcher proceeds. Any other ProviderSyncStatus variant (e.g. Pending, Failed, InProgress) causes an anyhow::bail! with the stored status and message, aborting the calling operation. It exists to prevent the launcher from running against an incompletely synchronized provider.
Solutions
- Read the embedded `message` in the error — it carries the reason the earlier sync failed — and fix that root cause first.
- Re-run the provider sync step so the status transitions to Synced before launching.
- Inspect the provider sync record in the codex-plus data store (db_path) to confirm the current status and reset/retry it.
- Check connectivity/upstream provider availability if the stored message indicates a network or API failure.
- If this occurs in tests, ensure the fixture actually completes the sync or asserts the bail for the intended non-Synced variant.
Example fix
// before
require_completed_provider_sync(&status, &message)?;
// after
if status != codex_plus_data::ProviderSyncStatus::Synced {
run_provider_sync(&mut service)?; // retry the sync before bailing
}
require_completed_provider_sync(&status, &message)?; Defensive patterns
Strategy: validation
Validate before calling
// check before invoking launcher paths that require sync
let status = service.load_provider_sync_status()?;
anyhow::ensure!(
status == codex_plus_data::ProviderSyncStatus::Synced,
"run provider sync first (current: {status:?})"
); Type guard
fn is_synced(status: &codex_plus_data::ProviderSyncStatus) -> bool {
matches!(status, codex_plus_data::ProviderSyncStatus::Synced)
} Try / catch
// propagate with context instead of losing the stored message
require_completed_provider_sync(&status, &message)
.context("launcher preflight: provider sync incomplete")?; Prevention
- Always run the sync step to completion before launching.
- Persist and read the stored sync `message` for root-cause diagnosis.
- Make sync resumable/idempotent so interrupted runs can be retried.
- Add a launcher preflight check that surfaces non-Synced states early with actionable text.
When it happens
Trigger: run_provider_sync (or the test launcher_accepts_only_a_completed_provider_sync) loads a codex_plus_data::ProviderSyncStatus from the data store and passes it to require_completed_provider_sync; the function bails when `*status != ProviderSyncStatus::Synced`, embedding the Debug status and stored message in the error. Raised at apps/codex-plus-launcher/src/main.rs:635.
Common situations: A previous sync crashed or was interrupted leaving status Pending/Failed; the data store was created but sync never ran; a prior sync recorded an error message (network, upstream API failure) that now surfaces here; tests injecting a non-Synced status on purpose.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- archived lookup task failed
- built-in Dream Skin theme cannot be deleted
- built-in Dream Skin theme is read-only
- cannot terminate Windows process id
- cannot wait for Windows process id
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/a55db788c264148f.
Report an issue: GitHub.
Appendix: source
Thrown at apps/codex-plus-launcher/src/main.rs:635
}
async fn shutdown_helper(&self, helper_port: u16) {
self.core.shutdown_helper(helper_port).await;
}
async fn terminate_codex(&self, launch: &codex_plus_core::launcher::CodexLaunch) {
self.core.terminate_codex(launch).await;
}
}
fn require_completed_provider_sync(
status: &codex_plus_data::ProviderSyncStatus,
message: &str,
) -> anyhow::Result<()> {
if *status == codex_plus_data::ProviderSyncStatus::Synced {
return Ok(());
}
anyhow::bail!("provider sync did not complete ({status:?}): {message}")
}
#[derive(Debug, Clone)]
struct LauncherDataService {
db_path: PathBuf,
backup_dir: PathBuf,
}
impl Default for LauncherDataService {
fn default() -> Self {
Self {
db_path: default_codex_db_path(),
backup_dir: codex_plus_core::paths::default_app_state_dir().join("backups"),
}
}
}
#[async_trait::async_trait]View on GitHub (pinned to b1ed92e5e4)