thedotmack/claude-mem · error · Error
sync hub status: response requires protocol_version 2
Error message
sync hub status: response requires protocol_version 2
What it means
The sync-hub status protocol requires protocol_version === 2. probeHubStatus rejects any other version with 'sync hub status: response requires protocol_version 2'. This prevents the client from interpreting an incompatible hub protocol.
Solutions
- Upgrade the hub (or the client) so both sides speak sync-hub protocol_version 2.
- If a deployment skew is detected, roll back the more recently deployed side until versions match.
- Check hub release notes for protocol_version changes and migration steps.
- For testing, update mock hub fixtures to emit protocol_version: 2.
Example fix
// before (hub)
res.json({ head_seq, projected_seq, epoch });
// after
res.json({ protocol_version: 2, epoch, head_seq, projected_seq }); Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(hubUrl + '/status');
const parsed = await res.json();
if (parsed?.protocol_version !== 2) {
throw new Error(`hub speaks protocol_version ${parsed?.protocol_version}; client requires 2 — upgrade hub`);
} Type guard
function isProtocolV2(v: unknown): v is { protocol_version: 2 } & Record<string, unknown> {
return typeof v === 'object' && v !== null && (v as any).protocol_version === 2;
} Try / catch
try {
const status = await cloudSync.statusWithHubProbe();
} catch (e) {
if (e.message === 'sync hub status: response requires protocol_version 2') {
logger.error('sync-hub protocol skew detected; halting sync until hub is upgraded');
disableSyncUntilVersionsMatch();
} else throw e;
} Prevention
- Version-check the hub at startup and fail fast on protocol skew
- Deploy client and hub protocol changes together (no rolling skew)
- Keep protocol_version negotiation explicit rather than guessing
- Test mock hubs with the exact protocol_version the client requires
When it happens
Trigger: Hub reports protocol_version 1 (or 3+), or omits the field, because the hub and client were built against different protocol revisions.
Common situations: Upgraded client talking to an old hub (or vice versa) after a deployment skew, self-hosted hub fork pinned to an older protocol, environment variable or build flag selecting a legacy protocol.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- [claude-mem] Failed to parse search results:
- sync hub status: projected_seq exceeds head_seq
- sync hub status: response is not JSON
- sync hub status: response must be an object
- sync hub status: response requires decimal-string…
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/c6d639da0aa6a7f4.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/sync/CloudSync.ts:670
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'
|| typeof record.projected_seq !== 'string'
) {
throw new Error('sync hub status: response requires decimal-string epoch/head_seq/projected_seq');
}
const epoch = assertCanonicalDecimal(record.epoch, { positive: true });
const headSeq = assertCanonicalDecimal(record.head_seq);
const projectedSeq = assertCanonicalDecimal(record.projected_seq);
if (compareCanonicalDecimals(projectedSeq, headSeq) > 0) {
throw new Error('sync hub status: projected_seq exceeds head_seq');
}
this.hubStatus = {
checkedAt,
reachable: true,
epoch,View on GitHub (pinned to d8bc9755e7)