hcengineering/platform · error · DatalakeError

Failed to complete multipart upload

Error message

Failed to complete multipart upload

What it means

DatalakeError thrown when the final POST to /upload/multipart/{workspace}/{object}/complete fails, so the uploaded parts are not assembled into the final object. fetchSafe errors (network failure or non-OK responses such as 404 unknown uploadId, 400 invalid part list) are caught and rethrown as this single error; the real cause is logged via ctx.error.

Source

Thrown at foundations/server/packages/datalake/src/client.ts:460

    parts: MultipartUploadPart[]
  ): Promise<ObjectMetadata> {
    const path = `/upload/multipart/${workspace}/${encodeURIComponent(objectName)}/complete`
    const url = new URL(concatLink(this.endpoint, path))
    url.searchParams.set('uploadId', multipart.uploadId)

    try {
      const res = await fetchSafe(ctx, url, {
        method: 'POST',
        body: JSON.stringify({ parts }),
        headers: {
          'Content-Type': 'application/json',
          ...this.headers
        }
      })
      return (await res.json()) as ObjectMetadata
    } catch (err: any) {
      ctx.error('failed to complete multipart upload', { workspace, objectName, err })
      throw new DatalakeError('Failed to complete multipart upload')
    }
  }

  private async multipartUploadAbort (
    ctx: MeasureContext,
    workspace: WorkspaceUuid,
    objectName: string,
    multipart: MultipartUpload
  ): Promise<void> {
    const path = `/upload/multipart/${workspace}/${encodeURIComponent(objectName)}/abort`
    const url = new URL(concatLink(this.endpoint, path))
    url.searchParams.set('uploadId', multipart.uploadId)

    try {
      await fetchSafe(ctx, url, { method: 'POST', headers: { ...this.headers } })
    } catch (err: any) {
      ctx.error('failed to abort multipart upload', { workspace, objectName, err })
      throw new DatalakeError('Failed to abort multipart upload')

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Read the wrapped err in ctx.error logs to identify the server response text.
  2. Retry the full uploadWithMultipart from scratch (fresh uploadId).
  3. Ensure all parts uploaded successfully before complete; reduce upload duration to avoid session expiry.
  4. Check datalake server logs for the complete-request failure.

Example fix

// before
await client.uploadWithMultipart(ctx, ws, name, data)
// after
try {
  await client.uploadWithMultipart(ctx, ws, name, data)
} catch (err) {
  if (err instanceof DatalakeError) {
    console.error('upload completion failed, restarting upload')
    await client.uploadWithMultipart(ctx, ws, name, data)
  } else throw err
}
Defensive patterns

Strategy: retry

Try / catch

try {
  await client.uploadWithMultipart(ctx, ws, name, data)
} catch (err) {
  if (err instanceof DatalakeError) {
    // restart with a fresh uploadId
    await client.uploadWithMultipart(ctx, ws, name, data)
  } else throw err
}

Prevention

When it happens

Trigger: uploadWithMultipart reaches the complete step and fetchSafe throws: network failure, expired/aborted uploadId, missing or malformed parts payload, or server 5xx.

Common situations: Long-running uploads where the server-side multipart session times out before complete is called; an earlier part upload failed silently; client/server version mismatch rejecting the parts JSON.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/3f0a57ed769ed5f5. Report an issue: GitHub.