hcengineering/platform · error

cannot complete upload with no parts

Error message

cannot complete upload with no parts

What it means

Complete() validates that at least one part was uploaded before asking storage to compose the object. If the parts list is empty (nothing was flushed via Write), it logs a warning and returns this error instead of creating a zero-part upload that storage would reject.

Source

Thrown at foundations/stream/internal/pkg/mediaconvert/multipart.go:174

	// flush any remaining data as last part
	if w.buffer.Len() > 0 {
		partNum := w.nextPartNum
		lastData := w.buffer.Bytes()

		part, err := w.storage.MultipartUploadPart(ctx, w.objectName, w.uploadID, partNum, lastData)
		if err != nil {
			w.logger.Error("multipart upload last part failed", zap.Error(err), zap.Int("partNumber", partNum))
			return errors.Wrap(err, "failed to upload last part")
		}

		w.bytesUploaded += int64(len(lastData))
		w.parts = append(w.parts, *part)
	}

	if len(w.parts) == 0 {
		w.logger.Warn("cannot complete upload with no parts")
		return errors.New("cannot complete upload with no parts")
	}

	if err := w.storage.MultipartUploadComplete(ctx, w.objectName, w.uploadID, w.parts); err != nil {
		w.logger.Error("multipart upload complete failed", zap.Error(err))
		return errors.Wrap(err, "failed to complete multipart upload")
	}

	w.completed = true
	w.logger.Info(
		"multipart upload completed",
		zap.Int64("bytesUploaded", w.bytesUploaded),
		zap.Int64("bytesWritten", w.bytesWritten),
	)

	return nil
}

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Ensure at least one chunk is written (Write) before calling Complete; special-case zero-byte files if supported
  2. Check earlier Write errors — this error usually masks a failed chunk pipeline
  3. Verify buffer/part accounting: confirm writes actually appended to parts, not just the local buffer
  4. Retry the whole upload from scratch if the source data is available

Example fix

// before
upload, _ := NewMultipartUpload(...)
_ = upload.Complete(ctx) // no parts written
// after
if err := upload.Write(ctx, data); err != nil { return err }
return upload.Complete(ctx)
Defensive patterns

Strategy: validation

Validate before calling

if len(data) == 0 {
    return errors.New("refusing multipart upload with no data")
}
// ensure at least one Write succeeded before Complete

Try / catch

if err := upload.Complete(ctx); err != nil {
    if strings.Contains(err.Error(), "no parts") {
        return ErrEmptyUpload
    }
    return err
}

Prevention

When it happens

Trigger: Calling Complete immediately after creating MultipartUpload without any successful Write; every Write failed (storage errors, context cancelled) so no parts accumulated; all buffered data was under the minimum part size and got dropped on flush failure.

Common situations: Empty file uploads not special-cased before multipart completion; storage outages causing all chunk uploads to silently fail before Complete; callers finishing an upload whose data pipeline never ran.

Related errors


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