{"record":{"id":"86e5c9b4acc464ab","repo":"hcengineering/platform","slug":"failed-to-initialize-multipart-upload","errorCode":null,"errorMessage":"Failed to initialize multipart upload","messagePattern":"Failed to initialize multipart upload","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"foundations/core/packages/storage-client/src/upload.ts","lineNumber":184,"sourceCode":"function throwIfAborted (signal?: AbortSignal): void {\n  if (signal?.aborted === true) {\n    throw new Error('Upload aborted')\n  }\n}\n\nasync function multipartUploadCreate (\n  baseUrl: string,\n  headers: Record<string, string>,\n  signal?: AbortSignal\n): Promise<{ uuid: string, uploadId: string }> {\n  const response = await fetch(baseUrl, {\n    signal,\n    method: 'POST',\n    headers\n  })\n\n  if (!response.ok) {\n    throw new Error('Failed to initialize multipart upload')\n  }\n\n  const { uuid, uploadId } = await response.json()\n  return { uuid, uploadId }\n}\n\nasync function multipartUploadComplete (\n  baseUrl: string,\n  headers: Record<string, string>,\n  uploadId: string,\n  parts: Array<{ partNumber: number, etag: string }>,\n  signal?: AbortSignal\n): Promise<void> {\n  const url = new URL(concatLink(baseUrl, '/complete'))\n  url.searchParams.set('uploadId', uploadId)\n\n  const response = await fetch(url, {\n    signal,","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/core/packages/storage-client/src/upload.ts#L166-L202","documentation":"multipartUploadCreate sends POST to the multipart upload base URL to initialize a session and expects a JSON body {uuid, uploadId}. If the fetch returns a non-ok status, it throws 'Failed to initialize multipart upload'. Because the status/body are discarded, auth errors, wrong endpoints and server failures all look identical.","triggerScenarios":"uploadMultipart starts (files >10MB trigger it via uploadFile) and the POST to baseUrl fails: 401/403 (bad Bearer token), 404 (baseUrl doesn't implement multipart endpoints), 405 (wrong HTTP method routing), or 5xx from the storage service.","commonSituations":"Storage service without multipart support (older deployment) receiving a large-file upload; baseUrl missing the /upload/multipart/<workspace>/<uuid> suffix; expired token during long sessions; reverse proxy rejecting POST without Content-Type expectations; hitting a regional endpoint that doesn't serve the workspace.","solutions":["Log response.status for the init request (patch or wrap uploadMultipart) to distinguish auth vs routing vs server error.","Verify the baseUrl is the full multipart endpoint and that the deployed storage service supports multipart uploads.","Refresh the Bearer token; 401 on init is the most common cause.","Retry with backoff on 5xx; if the service lacks multipart support, downgrade by uploading files in chunks below the 10MB single-shot threshold."],"exampleFix":"// before: baseUrl may be missing the multipart path\nawait uploadFile(token, ws, uuid, bigFile) // POST to wrong URL -> 404\n\n// after: ensure correct multipart URL\nconst url = concatLink(baseUrl, `/upload/multipart/${encodeURIComponent(ws)}/${encodeURIComponent(uuid)}`)\nawait uploadMultipart({ url, headers: { Authorization: `Bearer ${token}` }, body: bigFile })","handlingStrategy":"retry","validationCode":"// pre-flight: token present and endpoint reachable\nif (token === undefined) throw new Error('Missing token for multipart upload')\nconst probe = await fetch(baseUrl, { method: 'OPTIONS' })\nif (!probe.ok) console.warn('multipart endpoint not reachable:', baseUrl)","typeGuard":"null","tryCatchPattern":"let lastErr: unknown\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try { await uploadMultipart({ url, headers, body: file }, { signal }); return }\n  catch (err) {\n    if (err instanceof Error && err.message === 'Failed to initialize multipart upload') {\n      lastErr = err; await new Promise(r => setTimeout(r, 2 ** attempt * 500)); continue\n    }\n    throw err\n  }\n}\nthrow lastErr","preventionTips":["Confirm the deployed storage service supports multipart (files >10MB will use it).","Build the multipart URL with the full /upload/multipart/<workspace>/<uuid> path.","Refresh tokens before large uploads; init 401 is the top cause.","Log response.status on init failures to classify auth vs routing vs server errors."],"tags":["http","upload","multipart","network"],"backgroundTag":"multipart-upload-init-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}