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
- Check the status code and body snippet in the error; fix the corresponding issue (auth token, URL, hub health).
- Verify hub authentication credentials/token are present and not expired for 401/403.
- Confirm the hub URL/endpoint path is correct for 404s.
- Check hub server logs/health for 5xx causes and restart or redeploy the hub if it is unhealthy.
- 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
- Differentiate 4xx (fix credentials/URL) from 5xx (retry) when handling this error
- Log the body snippet included in the message — it names the hub-side cause
- Retry transient 502/503/504 with backoff before declaring the hub unreachable
- Monitor hub endpoint health independently of sync runs
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)