{"record":{"id":"ed97367ee228a9e7","repo":"thedotmack/claude-mem","slug":"sync-hub-status-response-status-body","errorCode":null,"errorMessage":"sync hub status ${response.status}: ${body}","messagePattern":"sync hub status (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sync/CloudSync.ts","lineNumber":596,"sourceCode":"  private async probeHubStatus(): Promise<void> {\n    let checkedAt = Date.now();\n    try {\n      const response = await this.fetchImpl(`${this.hubUrl}/v1/sync/status`, {\n        method: 'GET',\n        headers: {\n          'Authorization': `Bearer ${this.token}`,\n          'X-User-Id': this.userId,\n          'X-Device-Id': this.deviceId,\n          ...(this.deviceName ? { 'X-Device-Name': this.deviceName } : {}),\n        },\n        signal: AbortSignal.timeout(this.requestTimeoutMs),\n      });\n      checkedAt = Date.now();\n      const syncMode = response.headers.get('X-Sync-Mode');\n      if (syncMode !== null || response.ok) this.emitSyncMode(syncMode);\n      if (!response.ok) {\n        const body = (await response.text().catch(() => '')).slice(0, 200);\n        throw new Error(`sync hub status ${response.status}: ${body}`);\n      }\n\n      let parsed: unknown;\n      try {\n        parsed = await response.json();\n      } catch {\n        throw new Error('sync hub status: response is not JSON');\n      }\n      if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n        throw new Error('sync hub status: response must be an object');\n      }\n      const record = parsed as Record<string, unknown>;\n      if (record.protocol_version !== 2) {\n        throw new Error('sync hub status: response requires protocol_version 2');\n      }\n      if (\n        typeof record.epoch !== 'string'\n        || typeof record.head_seq !== 'string'","sourceCodeStart":578,"sourceCodeEnd":614,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/sync/CloudSync.ts#L578-L614","documentation":"Thrown by probeHubStatus when the GET to ${hubUrl}/v1/sync/status returned a non-OK HTTP status. The response body is read (up to 200 chars, swallow read errors) and included verbatim. X-Sync-Mode header is still emitted before throwing (presence regardless of status). This is the hub telling the client something is wrong at the HTTP layer (auth, rate limit, server error).","triggerScenarios":"The sync hub returns 4xx/5xx for the status probe: 401/403 for a bad or expired token (Authorization: Bearer ${token}), 404 for a wrong hubUrl, 429 for rate limiting, 5xx for hub outage. The X-User-Id/X-Device-Id headers did not satisfy the hub.","commonSituations":"Token expired or revoked; hubUrl misconfigured (wrong host/path/stage); user/device id headers missing or wrong; hub under maintenance returning 503; client version pointing at a hub that deprecated /v1/sync/status.","solutions":["Read the status code and body in the message — 401/403 means re-authenticate; 404 means fix hubUrl; 5xx means hub-side issue.","Verify the token is current and the X-User-Id/X-Device-Id headers match the account/device the hub expects.","Confirm hubUrl points at the correct hub environment (production vs staging) and includes the right base path.","For 429, back off the status polling cadence.","If 5xx persists, check the hub status page / contact the hub operator."],"exampleFix":"// before: stale token yields 401 on every probe\nhubUrl = 'https://sync.example.com'; token = oldToken;\n// after: refreshed token and correct hub base path\nhubUrl = 'https://sync.example.com'; token = await refreshToken();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isHubStatusHttpError(e: unknown): boolean {\n  return e instanceof Error && /^sync hub status \\d{3}:/i.test(e.message);\n}","tryCatchPattern":"try { await cloudSync.status(); }\ncatch (e) {\n  if (isHubStatusHttpError(e)) {\n    const code = Number(e.message.match(/status (\\d{3})/)?.[1]);\n    if (code === 401 || code === 403) { await refreshToken(); await cloudSync.status(); }\n    else if (code === 429) { await sleep(backoffMs); await cloudSync.status(); }\n    else { markHubUnreachable(e.message); }\n    return;\n  }\n  throw e;\n}","preventionTips":["Keep the bearer token fresh; refresh before it expires.","Verify hubUrl, X-User-Id, X-Device-Id match the account/device the hub expects.","Back off status polling on 429 to avoid rate limits.","Point hubUrl at the correct environment (prod vs staging) for the client version."],"tags":["cloud-sync","http","hub","auth","network"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}