{"record":{"id":"aaa8a4072c28bd07","repo":"hcengineering/platform","slug":"invalid-upload-id-aaa8a4","errorCode":null,"errorMessage":"invalid upload id","messagePattern":"invalid upload id","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"services/datalake/pod-datalake/src/handlers/multipart.ts","lineNumber":76,"sourceCode":"}\n\nexport async function handleMultipartUploadPart (\n  ctx: MeasureContext,\n  req: Request,\n  res: Response,\n  datalake: Datalake\n): Promise<void> {\n  const workspace = req.params.workspace as WorkspaceUuid\n  const partNumber = req.query.partNumber as string\n\n  let uuid: string\n  let uploadId: string\n\n  const upload = req.query.uploadId as string\n  try {\n    ;({ uuid, uploadId } = parseUploadId(upload))\n  } catch (err: any) {\n    res.status(400).send('invalid upload id')\n    return\n  }\n\n  if (!req.readable) {\n    res.status(400).send('missing body')\n    return\n  }\n\n  const { bucket } = await datalake.selectStorage(ctx, workspace)\n\n  const part = await bucket.uploadMultipartPart(ctx, uuid, { uploadId }, req, {\n    size: Number.parseInt(req.headers['content-length'] ?? '0'),\n    partNumber: Number.parseInt(partNumber)\n  })\n\n  ctx.info('multipart-part', { workspace, uuid, uploadId, partNumber })\n\n  res.status(200).json(part)","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/datalake/pod-datalake/src/handlers/multipart.ts#L58-L94","documentation":"handleMultipartUploadPart expects an uploadId query parameter that parses into a workspace uuid plus internal uploadId via parseUploadId. If parsing throws (malformed or absent query param), the handler responds 400 'invalid upload id'. The id must come from a prior multipart-init response.","triggerScenarios":"Calling the multipart part-upload endpoint with ?uploadId missing, empty, or a value that was never issued by multipart-init (or from another workspace/instance), so parseUploadId throws.","commonSituations":"Hand-constructed URLs guessing the uploadId format; reusing an uploadId after server restart when it was kept only in memory; copying an id between workspaces.","solutions":["Pass the exact uploadId string returned by the multipart-init endpoint as the uploadId query parameter.","Ensure the uploadId belongs to the same workspace as the request path.","Reinitialize the multipart upload if the original id was lost or the server restarted."],"exampleFix":"// before\nfetch(`${base}/${ws}/multipart/${name}/part?uploadId=abc`)\n// after\nconst { uploadId } = await initMultipart(ws, name)\nfetch(`${base}/${ws}/multipart/${name}/part?uploadId=${encodeURIComponent(uploadId)}`)","handlingStrategy":"validation","validationCode":"if (!uploadId || typeof uploadId !== 'string') {\n  throw new Error('uploadId from multipart-init is required')\n}","typeGuard":"function isUploadId(v: unknown): v is string {\n  return typeof v === 'string' && v.length > 0\n}","tryCatchPattern":"const res = await fetch(partUrl, opts)\nif (res.status === 400 && (await res.text()) === 'invalid upload id') {\n  // re-init multipart upload and retry with fresh id\n  const init = await initMultipart(ws, name)\n  return uploadPart(init.uploadId, part)\n}","preventionTips":["Always take uploadId verbatim from the init response; never construct it manually.","Keep the id associated with its workspace and upload session.","Re-init the upload after server restarts or unknown-id errors."],"tags":["http","multipart","validation","bad-request"],"backgroundTag":"invalid-upload-id","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}