{"record":{"id":"b15aafcd889caed6","repo":"thedotmack/claude-mem","slug":"sync-hub-status-response-requires-decimal-string","errorCode":null,"errorMessage":"sync hub status: response requires decimal-string epoch/head_seq/projected_seq","messagePattern":"sync hub status: response requires decimal-string epoch/head_seq/projected_seq","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sync/CloudSync.ts","lineNumber":617,"sourceCode":"      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'\n        || typeof record.projected_seq !== 'string'\n      ) {\n        throw new Error('sync hub status: response requires decimal-string epoch/head_seq/projected_seq');\n      }\n      const epoch = assertCanonicalDecimal(record.epoch, { positive: true });\n      const headSeq = assertCanonicalDecimal(record.head_seq);\n      const projectedSeq = assertCanonicalDecimal(record.projected_seq);\n      if (compareCanonicalDecimals(projectedSeq, headSeq) > 0) {\n        throw new Error('sync hub status: projected_seq exceeds head_seq');\n      }\n      this.hubStatus = {\n        checkedAt,\n        reachable: true,\n        epoch,\n        headSeq,\n        projectedSeq,\n        error: null,\n      };\n    } catch (error) {\n      const raw = error instanceof Error ? error.message : String(error);\n      const safe = this.token === '' ? raw : raw.split(this.token).join('[REDACTED]');","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/sync/CloudSync.ts#L599-L635","documentation":"Thrown when any of epoch, head_seq, or projected_seq on the status object is not a string (typeof check fails). All three must be decimal strings (canonical form, validated further by assertCanonicalDecimal with epoch requiring positive). The hub serializes large uint64 sequence numbers as strings to avoid JS number precision loss, so a number or missing field is rejected here.","triggerScenarios":"The hub returned epoch/head_seq/projected_seq as JSON numbers, omitted one, or sent null/empty. assertCanonicalDecimal would also reject non-canonical strings (leading zeroes, non-base-10), but the typeof guard catches the non-string cases first.","commonSituations":"Hub version that serializes sequences as numbers instead of strings; a field renamed in a hub update; a proxy stripping fields; a hub bug emitting null after an internal error.","solutions":["Log the raw record to see which field is missing or mistyped.","Ensure the hub emits epoch/head_seq/projected_seq as canonical decimal strings (no leading zeros, base-10, within uint64).","Align hub and client versions so the field shapes match the v2 contract.","epoch must additionally be positive (non-zero)."],"exampleFix":"// before: hub emits numbers\n// {\"protocol_version\":2,\"epoch\":1,\"head_seq\":42,\"projected_seq\":42}\n// after: hub emits decimal strings\n// {\"protocol_version\":2,\"epoch\":\"1\",\"head_seq\":\"42\",\"projected_seq\":\"42\"}","handlingStrategy":"validation","validationCode":null,"typeGuard":"function isHubStatusBadDecimalFields(e: unknown): boolean {\n  return e instanceof Error && /sync hub status: response requires decimal-string epoch\\/head_seq\\/projected_seq/i.test(e.message);\n}","tryCatchPattern":"try { await cloudSync.status(); }\ncatch (e) { if (isHubStatusBadDecimalFields(e)) { markHubMisconfigured(e.message); return; } throw e; }","preventionTips":["Ensure the hub serializes epoch/head_seq/projected_seq as canonical decimal strings (base-10, no leading zeros, within uint64).","epoch must additionally be positive (non-zero).","Contract-test the status response shape to catch hub regressions before clients do.","Keep hub and client versions aligned on the decimal-string convention."],"tags":["cloud-sync","hub","serialization","decimal-string","protocol"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}