hashicorp/terraform · error
failed to upload part: %s
Error message
failed to upload part: %s
What it means
Raised while collecting worker responses in multiPartUploadImpl when an uploaded-part response is structurally invalid: response.error is set, or partNumber is nil, or response.response.ETag is nil. The commit phase needs both a part number and an ETag per part, so a response missing either cannot be committed. (Per-worker hard upload failures are instead reported via errChan as 'failed to upload part %d'.)
Source
Thrown at internal/backend/remote-state/oci/multipart_upload.go:126
ctx.uploadPartsWorker()
}()
}
wg.Wait()
close(osUploadPartResponses)
close(errChan)
// Collect errors from workers
for workerErr := range errChan {
if workerErr != nil {
return workerErr
}
}
commitMultipartUploadPartDetails := make([]objectstorage.CommitMultipartUploadPartDetails, len(sourceBlocks))
i := 0
for response := range osUploadPartResponses {
if response.error != nil || response.partNumber == nil || response.response.ETag == nil {
return fmt.Errorf("failed to upload part: %s", response.error)
}
partNumber, etag := *response.partNumber, *response.response.ETag
commitMultipartUploadPartDetails[i] = objectstorage.CommitMultipartUploadPartDetails{
PartNum: common.Int(partNumber),
Etag: common.String(etag),
}
i++
}
if len(commitMultipartUploadPartDetails) != len(sourceBlocks) {
abortReq := objectstorage.AbortMultipartUploadRequest{
UploadId: multipartUploadResponse.MultipartUpload.UploadId,
NamespaceName: multipartUploadResponse.Namespace,
BucketName: multipartUploadResponse.Bucket,
ObjectName: multipartUploadResponse.Object,
}
_, abortErr := multipartUploadData.client.objectStorageClient.AbortMultipartUpload(context.Background(), abortReq)
if abortErr != nil {View on GitHub (pinned to c9def3e214)
Solutions
- Re-run the apply; an anomalous missing-ETag response is usually transient.
- Check the OCI-SDK version (oci-go-sdk/v65) is current and compatible with the object storage service response shape.
- Capture the OpcRequestId of the offending UploadPart call from TF_LOG=TRACE to report to OCI support.
- If it recurs, fall back is automatic via client.Put (single-part) when size permits; otherwise reduce state size to avoid multipart.
Defensive patterns
Strategy: retry
Validate before calling
// No caller-side validation can prevent an anomalous missing-ETag response; // ensure SDK version is current before relying on response shape.
Type guard
// Detect the structural defect after collection:
if response.error != nil || response.partNumber == nil || response.response.ETag == nil {
// cannot commit this part
} Try / catch
for response := range osUploadPartResponses {
if response.error != nil || response.partNumber == nil || response.response.ETag == nil {
return fmt.Errorf("failed to upload part: %s", response.error)
}
// ...
} Prevention
- Keep oci-go-sdk up to date so UploadPart response parsing is current.
- Retry on anomalous responses; usually transient.
- Capture OpcRequestId via TF_LOG=TRACE for support.
When it happens
Trigger: Iterating osUploadPartResponses (multipart_upload.go:124) yields a response where response.error != nil, response.partNumber == nil, or response.response.ETag == nil — e.g. the OCI service accepted the UploadPart call but returned no ETag, or an SDK-level anomaly produced an incomplete response object.
Common situations: An OCI/SDK anomaly returning a 2xx UploadPart response with no ETag header; an unexpected response shape after an SDK upgrade; rare service hiccup that the retry policy did not smooth over.
Related errors
- not all parts uploaded successfully, multipart upload aborte
- failed to access object HttpStatusCode: %d OpcRequestId: %s
- object %q is empty
- uploadSinglePartObject: data is empty
- failed to unmarshal JSON data into LockInfo struct: %w
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/24599b29238a6e50.
Report an issue: GitHub.