{"record":{"id":"01d49568147a7b72","repo":"thedotmack/claude-mem","slug":"push-res-status-await-res-text-catch-slice-0-200","errorCode":null,"errorMessage":"push ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}","messagePattern":"push (.+?): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workers/sync-hub/canary/canary.ts","lineNumber":240,"sourceCode":"\t\t\torigin_local_id: localId,\n\t\t\tpayload,\n\t\t\tpayload_schema_version: 2,\n\t\t\tpayload_sha256: await sha256Base64Url(canonicalJson(payload)),\n\t\t};\n\t\tconst body = canonicalJson(envelope);\n\t\tconst operationSha256 = await sha256Base64Url(body);\n\t\tconst res = await fetch(`${this.args.hub}/v1/sync/ops`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { ...this.headers(deviceId), \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tprotocol_version: 2,\n\t\t\t\tops: [{ body, operation_sha256: operationSha256 }],\n\t\t\t}),\n\t\t\tsignal: AbortSignal.timeout(this.args.timeoutMs),\n\t\t});\n\t\tthis.noteMode(res);\n\t\tif (!res.ok) {\n\t\t\tthrow new Error(`push ${res.status}: ${(await res.text().catch(() => \"\")).slice(0, 200)}`);\n\t\t}\n\t\tconst parsed = (await res.json()) as {\n\t\t\tacked: Array<{ operation_sha256: string; seq: string }>;\n\t\t\thead_seq: string;\n\t\t};\n\t\tconst ack = parsed.acked.find((a) => a.operation_sha256 === operationSha256);\n\t\tif (!ack) throw new Error(\"push response did not ack the canary op\");\n\t\treturn { seq: ack.seq, headSeq: parsed.head_seq, opSha: operationSha256 };\n\t}\n\n\tprivate async pull(\n\t\tdeviceId: string,\n\t\tsince: string,\n\t): Promise<{ ops: Array<{ seq: string; operation_sha256: string }>; headSeq: string }> {\n\t\tconst res = await fetch(`${this.args.hub}/v1/sync/changes?since=${since}&limit=500`, {\n\t\t\theaders: this.headers(deviceId),\n\t\t\tsignal: AbortSignal.timeout(this.args.timeoutMs),\n\t\t});","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/workers/sync-hub/canary/canary.ts#L222-L258","documentation":"The sync-hub canary's push method POSTs an operation to the hub and expects an OK response containing an ack for the operation's SHA-256. If the HTTP response status is not ok, it throws with the status code and the first 200 characters of the response body (body read failures degrade to an empty string). This surfaces server-side rejection details for debugging the sync protocol.","triggerScenarios":"The hub returns a non-2xx status to the push request — e.g. 409 conflict on a duplicate operation_sha256, 413 payload too large, 500 server error, 503 during maintenance.","commonSituations":"Replaying an operation the hub already acked; hub deployment/maintenance window; oversized operation bodies; auth token expiry on the canary client.","solutions":["Inspect the response body snippet in the error to identify the hub's rejection reason","Handle 409 conflicts idempotently — treat already-acked operations as success","Retry with backoff on 5xx/503 responses","Check hub auth/credentials if the status is 401/403"],"exampleFix":"// before\nawait canary.push(body, operationSha256); // throws on !res.ok\n// after\ntry {\n  await canary.push(body, operationSha256);\n} catch (e) {\n  if (String(e).startsWith('push 409')) return; // already acked\n  await backoffRetry(() => canary.push(body, operationSha256));\n}","handlingStrategy":"retry","validationCode":"const body = JSON.stringify(ops);\nif (body.length > MAX_PUSH_BYTES) throw new Error('operation too large for single push');","typeGuard":null,"tryCatchPattern":"try { await client.push(body, sha); }\ncatch (e) {\n  if (/push 409/.test(String(e))) return; // duplicate op, treat as acked\n  if (/push 5\\d\\d/.test(String(e))) { await backoffRetry(() => client.push(body, sha)); return; }\n  throw e;\n}","preventionTips":["Make pushes idempotent via operation_sha256 and treat 409 as success","Use retry with exponential backoff for 5xx responses","Keep operation bodies under hub size limits","Refresh auth tokens before they expire on long-running canaries"],"tags":["http","sync","api"],"backgroundTag":"http-error-response","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}