{"record":{"id":"24599b29238a6e50","repo":"hashicorp/terraform","slug":"failed-to-upload-part-s","errorCode":null,"errorMessage":"failed to upload part: %s","messagePattern":"failed to upload part: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/oci/multipart_upload.go","lineNumber":126,"sourceCode":"\t\t\tctx.uploadPartsWorker()\n\t\t}()\n\t}\n\n\twg.Wait()\n\tclose(osUploadPartResponses)\n\tclose(errChan)\n\n\t// Collect errors from workers\n\tfor workerErr := range errChan {\n\t\tif workerErr != nil {\n\t\t\treturn workerErr\n\t\t}\n\t}\n\tcommitMultipartUploadPartDetails := make([]objectstorage.CommitMultipartUploadPartDetails, len(sourceBlocks))\n\ti := 0\n\tfor response := range osUploadPartResponses {\n\t\tif response.error != nil || response.partNumber == nil || response.response.ETag == nil {\n\t\t\treturn fmt.Errorf(\"failed to upload part: %s\", response.error)\n\t\t}\n\t\tpartNumber, etag := *response.partNumber, *response.response.ETag\n\t\tcommitMultipartUploadPartDetails[i] = objectstorage.CommitMultipartUploadPartDetails{\n\t\t\tPartNum: common.Int(partNumber),\n\t\t\tEtag:    common.String(etag),\n\t\t}\n\t\ti++\n\t}\n\n\tif len(commitMultipartUploadPartDetails) != len(sourceBlocks) {\n\t\tabortReq := objectstorage.AbortMultipartUploadRequest{\n\t\t\tUploadId:      multipartUploadResponse.MultipartUpload.UploadId,\n\t\t\tNamespaceName: multipartUploadResponse.Namespace,\n\t\t\tBucketName:    multipartUploadResponse.Bucket,\n\t\t\tObjectName:    multipartUploadResponse.Object,\n\t\t}\n\t\t_, abortErr := multipartUploadData.client.objectStorageClient.AbortMultipartUpload(context.Background(), abortReq)\n\t\tif abortErr != nil {","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/oci/multipart_upload.go#L108-L144","documentation":"After the workers complete, the code iterates the osUploadPartResponses channel and rejects any response whose error is non-nil OR whose partNumber/ETag is nil. Indicates at least one part-upload returned an error or a malformed success (missing ETag/partNumber). Note the format uses %s on response.error, which can be nil when only partNumber/ETag is missing — the message may read 'failed to upload part: %!s(<nil>)'.","triggerScenarios":"A worker's UploadPart returned an OCI/transport error (throttling, auth expiry, 5xx); a worker returned success but with nil ETag or nil partNumber; transient failures under 10-way parallel uploads.","commonSituations":"Bandwidth saturated by 10 concurrent part uploads; token expiring during a long multipart upload; throttling (429) under high CI concurrency; partial network failure affecting one worker.","solutions":["Check worker logs (TF_LOG=DEBUG) for the per-part error — the aggregated message can hide it when response.error is nil.","Reduce parallelism pressure — fewer/smaller parts (raise DefaultFilePartSize) lowers the chance of any single part failing.","Refresh long-lived credentials before starting a large upload; multipart uploads can outlive a short token TTL.","Retry the whole Put; the upload was aborted/abandoned on this path."],"exampleFix":"// before: 10 workers upload parts against a saturated link -> intermittent 317\n// after: raise part size to reduce part count and per-part bandwidth pressure\nvar DefaultFilePartSize int64 = 256 * 1024 * 1024\n// and run with TF_LOG=DEBUG to capture the per-part error\n//   terraform apply -auto-approve 2>tf.log\n//   grep 'failed to upload part' tf.log","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isPartUploadErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"failed to upload part\")\n}","tryCatchPattern":"// On per-part failure, capture the worker error (it may be nil when only ETag is missing)\nif response.error != nil || response.partNumber == nil || response.response.ETag == nil {\n    err := response.error\n    if err == nil { err = fmt.Errorf(\"part %d upload returned nil ETag/partNumber\", deref(response.partNumber)) }\n    return nil, fmt.Errorf(\"failed to upload part: %w\", err)\n}","preventionTips":["Run with TF_LOG=DEBUG to capture the per-part worker error (the aggregate can show nil).","Raise DefaultFilePartSize to reduce part count and per-part bandwidth pressure.","Refresh long-lived credentials before starting a large multipart upload.","Throttle CI concurrency against the same bucket to avoid per-part throttling."],"tags":["oci","multipart-upload","concurrency","network","diagnostics"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}