{"record":{"id":"187bc58886db2c68","repo":"jackwener/OpenCLI","slug":"tos-upload-part-partnumber-failed-with-status","errorCode":null,"errorMessage":"TOS upload part ${partNumber} failed with status ${res.status}: ${res.body}","messagePattern":"TOS upload part (.+?) failed with status (.+?): (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"critical","filePath":"clis/douyin/_shared/tos-upload.js","lineNumber":230,"sourceCode":"    const crc32 = crc32Hex(data);\n    const url = `${gatewayBaseUrl(tosUrl)}?uploadid=${encodeURIComponent(uploadId)}&part_number=${partNumber}&phase=transfer`;\n    const headers = {\n        ...gatewayHeaders(auth, uploadHeader, userId),\n        'Content-CRC32': crc32,\n        'Content-Type': 'application/octet-stream',\n        'X-Use-Init-Upload-Optimize': '1',\n        'X-Use-Large-Local-Cache': '1',\n    };\n    const res = await tosRequest({ method: 'POST', url, headers, body: data });\n    let parsed;\n    try {\n        parsed = JSON.parse(res.body);\n    }\n    catch {\n        parsed = null;\n    }\n    if (res.status !== 200 || parsed?.code !== 2000) {\n        throw new CommandExecutionError(`TOS upload part ${partNumber} failed with status ${res.status}: ${res.body}`, 'Check that TOS upload authorization is valid and not expired.');\n    }\n    return parsed?.data?.crc32 || crc32;\n}\n// ── Phase 3: Complete multipart upload ───────────────────────────────────────\nasync function completeMultipartUpload(tosUrl, uploadId, parts, auth, uploadHeader, userId) {\n    const url = `${gatewayBaseUrl(tosUrl)}?uploadmode=part&phase=finish&uploadid=${encodeURIComponent(uploadId)}`;\n    const body = parts\n        .sort((a, b) => a.partNumber - b.partNumber)\n        .map(p => `${p.partNumber}:${p.crc32}`)\n        .join(',');\n    const res = await tosRequest({\n        method: 'POST',\n        url,\n        headers: gatewayHeaders(auth, uploadHeader, userId),\n        body,\n    });\n    let parsed;\n    try {","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/tos-upload.js#L212-L248","documentation":"uploadPart PUTs one part of the file to TOS and expects HTTP 200 with parsed.code === 2000 (application-level success). This CommandExecutionError is thrown when either the HTTP status or the JSON code indicates the part upload was rejected.","triggerScenarios":"tosUpload loop -> uploadPart with a part buffer; server returns non-200, or 200 with body code != 2000 — expired auth mid-upload, wrong CRC32 handling, throttling, or part-data corruption.","commonSituations":"Long uploads where the TOS auth expires between init and later parts; network interruptions; resuming with a stale uploadId after server-side cleanup.","solutions":["Re-fetch upload authorization and restart/resume the upload","Retry the failing part with backoff (transient network errors)","Check res.body for server-side reason (throttle, auth, signature)","Verify the part buffer and crc32Hex computation are correct and the file wasn't modified mid-upload"],"exampleFix":"// before\nawait uploadPart(tosUrl, partNumber, uploadId, buffer, auth, uploadHeader, userId);\n// after\nfor (let i = 0; i < 3; i++) {\n  try { return await uploadPart(tosUrl, partNumber, uploadId, buffer, auth, uploadHeader, userId); }\n  catch (e) { await sleep(1000 * 2 ** i); }\n}\nthrow new Error('part upload failed after retries');","handlingStrategy":"retry","validationCode":"// Pre-check upload info freshness before the part loop\nif (!uploadInfo || !uploadInfo.auth) throw new Error('missing TOS auth before part upload');","typeGuard":null,"tryCatchPattern":"try { await uploadPart(tosUrl, partNumber, uploadId, buffer, auth, uploadHeader, userId); }\ncatch (e) {\n  if (String(e.message).startsWith('TOS upload part')) {\n    await sleep(2000);\n    await uploadPart(tosUrl, partNumber, uploadId, buffer, auth, uploadHeader, userId); // resume state keeps progress\n  } else throw e;\n}","preventionTips":["Rely on the library's resume state to re-send only failed parts","Add bounded exponential-backoff retries around part uploads","Keep the file unmodified during upload so CRC32 matches","Re-acquire auth for very large files whose upload outlives the token TTL"],"tags":["upload","http","retry","douyin"],"backgroundTag":"upload-part-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}