{"record":{"id":"40411e8ee1c34778","repo":"can1357/oh-my-pi","slug":"share-upload-to-base-failed-http-res-status","errorCode":null,"errorMessage":"Share upload to ${base} failed: HTTP ${res.status}${detail ? ` (${detail})` : \"\"}","messagePattern":"Share upload to (.+?) failed: HTTP (.+?)(.+?)\\)` : \"\"\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/export/share.ts","lineNumber":679,"sourceCode":"\t\tsealedBytes: forServer.sealed.byteLength,\n\t};\n}\n\n/** POST the sealed blob to the share server; returns the assigned id. */\nasync function uploadToServer(sealed: Uint8Array, base: string): Promise<string> {\n\tlet res: Response;\n\ttry {\n\t\tres = await fetch(base, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/octet-stream\" },\n\t\t\tbody: sealed,\n\t\t});\n\t} catch (err) {\n\t\tthrow new Error(`Share upload to ${base} failed: ${err instanceof Error ? err.message : String(err)}`);\n\t}\n\tif (!res.ok) {\n\t\tconst detail = (await res.text().catch(() => \"\")).trim().slice(0, 200);\n\t\tthrow new Error(`Share upload to ${base} failed: HTTP ${res.status}${detail ? ` (${detail})` : \"\"}`);\n\t}\n\tconst body = (await res.json().catch(() => null)) as { id?: unknown } | null;\n\tconst id = body && typeof body.id === \"string\" ? body.id : \"\";\n\tif (!/^[A-Za-z0-9_-]{10,64}$/.test(id)) {\n\t\tthrow new Error(`Share upload to ${base} failed: server returned no usable id`);\n\t}\n\treturn id;\n}\n","sourceCodeStart":661,"sourceCodeEnd":688,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/export/share.ts#L661-L688","documentation":"uploadToServer treats any non-2xx HTTP response from the share server as a failure. It includes the HTTP status and up to 200 chars of the response body (detail) in the error so the caller can see why the server rejected the upload (auth, size limit, rate limit, bad request).","triggerScenarios":"The POST to the share server completed but returned e.g. 413 (payload too large), 401/403 (auth), 429 (rate limited), or 500; the server's response body text is appended as detail.","commonSituations":"Session exceeding the server's configured max body size; missing or expired share auth token; server rate-limiting frequent shares; reverse proxy (nginx/Cloudflare) rejecting large bodies; share server bug returning 5xx.","solutions":["Read the HTTP status and detail in the message: 413 → session too large (trim content or raise server body limit); 401/403 → fix credentials; 429 → wait and retry; 5xx → check server logs.","If 413: reduce session size (same remedies as 'session too large') or increase the server/proxy body-size limit (e.g. client_max_body_size).","If 401/403: re-authenticate or update the share token in config/env.","If 429: back off and retry later.","If 5xx: retry once, then inspect the share server deployment."],"exampleFix":"// before\nawait share.forServer(session); // fails: HTTP 413 (payload too large)\n// after\n// raise nginx limit on the share server: client_max_body_size 25m;\nawait share.forServer(session);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const id = await uploadToServer(base, sealed);\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  const m = msg.match(/HTTP (\\d+)/);\n  if (m) {\n    const status = Number(m[1]);\n    if (status === 413) { /* trim session or raise server body limit */ }\n    else if (status === 401 || status === 403) { /* refresh auth */ }\n    else if (status === 429) { /* back off and retry */ }\n  } else throw err;\n}","preventionTips":["Match server body-size limits (nginx client_max_body_size) to expected session sizes","Keep share auth tokens fresh and configured","Handle 429 with backoff instead of hammering the endpoint","Watch server-side error rates; 5xx usually means server deployment issues"],"tags":["network","http","upload","server-error","sharing"],"backgroundTag":"http-error-response","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}