thedotmack/claude-mem · error · Error

sync hub status

Error message

sync hub status ${response.status}: ${body}

What it means

CloudSync.probeHubStatus fetches the sync hub status endpoint and requires an OK (2xx) HTTP response. Any non-OK response is rejected with 'sync hub status <status>: <first 200 chars of body>', surfacing the hub's own error output. The probe result marks the hub unreachable and the sync mode falls back accordingly.

Solutions

  1. Check the status code and body snippet in the error; fix the corresponding issue (auth token, URL, hub health).
  2. Verify hub authentication credentials/token are present and not expired for 401/403.
  3. Confirm the hub URL/endpoint path is correct for 404s.
  4. Check hub server logs/health for 5xx causes and restart or redeploy the hub if it is unhealthy.
  5. Implement retry with backoff for transient 5xx/gateway responses in statusWithHubProbe.

Example fix

// before
const status = await cloudSync.statusWithHubProbe();
// after
let status;
try {
  status = await cloudSync.statusWithHubProbe();
} catch (e) {
  if (/sync hub status 5\d\d/.test(e.message)) {
    status = await cloudSync.statusWithHubProbe(); // retry after backoff
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// probe reachability + expected status before the real call
const pre = await fetch(hubUrl + '/status', { method: 'HEAD' });
if (pre.status === 401) throw new Error('hub auth required');
if (!pre.ok) throw new Error(`hub unhealthy: ${pre.status}`);

Try / catch

try {
  const status = await cloudSync.statusWithHubProbe();
} catch (e) {
  const m = /^sync hub status (\d{3}):/.exec(e.message);
  if (m && +m[1] >= 500) await retryWithBackoff(() => cloudSync.statusWithHubProbe());
  else if (m && (+m[1] === 401 || +m[1] === 403)) await refreshHubCredentials();
  else throw e;
}

Prevention

When it happens

Trigger: HTTP response from the hub with status outside 2xx: 401/403 auth failures, 404 wrong URL/path, 500/503 hub-side errors, or gateway 502/504.

Common situations: Expired or missing hub credentials, misconfigured hub base URL, hub service down or deploying, reverse proxy returning 502 while the hub restarts.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/ed97367ee228a9e7. Report an issue: GitHub.

Appendix: source

Thrown at src/services/sync/CloudSync.ts:656

  private async probeHubStatus(): Promise<void> {
    let checkedAt = Date.now();
    try {
      const response = await this.fetchImpl(`${this.hubUrl}/v1/sync/status`, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'X-User-Id': this.userId,
          'X-Device-Id': this.deviceId,
          ...(this.deviceName ? { 'X-Device-Name': this.deviceName } : {}),
        },
        signal: AbortSignal.timeout(this.requestTimeoutMs),
      });
      checkedAt = Date.now();
      const syncMode = response.headers.get('X-Sync-Mode');
      if (syncMode !== null || response.ok) this.emitSyncMode(syncMode);
      if (!response.ok) {
        const body = (await response.text().catch(() => '')).slice(0, 200);
        throw new Error(`sync hub status ${response.status}: ${body}`);
      }

      let parsed: unknown;
      try {
        parsed = await response.json();
      } catch {
        throw new Error('sync hub status: response is not JSON');
      }
      if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
        throw new Error('sync hub status: response must be an object');
      }
      const record = parsed as Record<string, unknown>;
      if (record.protocol_version !== 2) {
        throw new Error('sync hub status: response requires protocol_version 2');
      }
      if (
        typeof record.epoch !== 'string'
        || typeof record.head_seq !== 'string'

View on GitHub (pinned to d8bc9755e7)