{"record":{"id":"c85b8a36df7051f0","repo":"JuliusBrussee/caveman","slug":"sync-incomplete-failures-join","errorCode":null,"errorMessage":"sync incomplete — ${failures.join(\"; \")}","messagePattern":"sync incomplete — (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":10150,"sourceCode":"      if (out.firstSync) console.log(SYNC_DISCLOSURE);\n      console.log(syncSavingsLine(out));\n    }\n  } else {\n    failures.push(`local spans: ${syncLaneError(savingsLane.reason)}`);\n  }\n  if (practicesLane.status === \"fulfilled\") {\n    if (practicesLane.value.kind === \"synced\") {\n      console.log(`synced ${practicesLane.value.findings} local practice findings · basis: inferred (tokens only; no payload evidence)`);\n    }\n  } else {\n    failures.push(`practice findings: ${syncLaneError(practicesLane.reason)}`);\n  }\n  if (localScanLane.status === \"fulfilled\") {\n    if (localScanLane.value.kind === \"synced\") console.log(localScanSyncLine(localScanLane.value));\n  } else {\n    failures.push(`local scan: ${syncLaneError(localScanLane.reason)}`);\n  }\n  if (failures.length > 0) throw new Error(`sync incomplete — ${failures.join(\"; \")}`);\n}\n\nfunction syncLaneError(reason: unknown): string {\n  return reason instanceof Error ? reason.message : String(reason);\n}\n\n// syncAfterLogin runs the same sync once right after a successful login so the\n// dashboard immediately shows what the local proxy already measured. Strictly\n// best-effort: a sync failure never fails the login.\nasync function syncAfterLogin() {\n  try {\n    const cfg = await config();\n    if (!cfg.token) return;\n    const [savingsLane, practicesLane, localScanLane] = await Promise.allSettled([\n      syncLocalSavings(cfg),\n      syncLocalPracticeFindings(cfg),\n      syncPendingLocalScan(cfg),\n    ] as const);","sourceCodeStart":10132,"sourceCodeEnd":10168,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L10132-L10168","documentation":"Thrown by the CLI's explicit sync path after it fans local-state uploads out into parallel lanes (practice findings, local scan) using allSettled-style handling. Each rejected lane appends a human-readable '<lane>: <reason>' string; if any lane failed, one aggregated error is thrown so partial success is never reported as a complete sync. The nearby syncAfterLogin helper deliberately does NOT throw (best-effort after login), so hitting this message means the user-invoked sync command ran.","triggerScenarios":"Running the sync command when at least one lane rejects: the local proxy/engine subprocess exits non-zero, the proxy is not running or not listening, the engine binary is missing from PATH/CAVEMAN_ENGINE_BIN, or the cloud API call fails on auth or network. The message enumerates every failed lane joined by '; '.","commonSituations":"Fresh machine that never ran `caveman setup` (engine/proxy binaries absent), proxy daemon stopped or crashed mid-run, expired or rotated auth token, transient network loss during upload, version skew between CLI and local proxy.","solutions":["Read the joined lane reasons to identify which sync failed (practice findings vs local scan) before changing anything","Verify the local proxy is running and healthy (e.g. `caveman status` or its stats endpoint)","Run `caveman setup` to confirm engine/proxy binaries resolve; set CAVEMAN_ENGINE_BIN if the engine lives elsewhere","If a lane reason mentions 401/403 or token expiry, re-run `caveman login` and retry","Re-run the sync — lane failures caused by transient network errors usually clear on retry"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight the lanes' shared dependency so transient sync failures never start.\nimport { spawnSync } from 'node:child_process';\nconst probe = spawnSync(process.env.CAVEMAN_ENGINE_BIN ?? 'caveman-engine', ['--version']);\nif (probe.error) throw new Error(`engine missing: ${String(probe.error.message)}`);","typeGuard":null,"tryCatchPattern":"try {\n  await runSync();\n} catch (e) {\n  const msg = (e as Error).message;\n  if (msg.startsWith('sync incomplete')) {\n    // lane names + reasons are '; '-joined — retry only the failed lanes, or the whole sync once\n  } else throw e;\n}","preventionTips":["Start the local proxy and confirm it is healthy before invoking sync","Run `caveman setup` on new machines so engine/proxy binaries exist","Treat sync as best-effort in pipelines: catch the aggregate error, log lane reasons, and do not fail the build on it"],"tags":["sync","allsettled","aggregated-error","proxy","cli"],"backgroundTag":"partial-sync-failure","analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}