{"record":{"id":"9ad55099b6905813","repo":"hashicorp/terraform","slug":"error-reading-source-block-d-w","errorCode":null,"errorMessage":"error reading source block %d: %w","messagePattern":"error reading source block (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/backend/remote-state/oci/multipart_upload.go","lineNumber":212,"sourceCode":"func SplitSizeToOffsetsAndLimits(size int64) ([]int64, int64, error) {\n\tpartSize := DefaultFilePartSize\n\ttotalParts := (size + partSize - 1) / partSize\n\tif totalParts > MaxCount {\n\t\treturn nil, 0, fmt.Errorf(\"file exceeds maximum part count\")\n\t}\n\toffsets := make([]int64, totalParts)\n\tfor i := range offsets {\n\t\toffsets[i] = int64(i) * partSize\n\t}\n\treturn offsets, partSize, nil\n}\n\nfunc (ctx *objectStorageMultiPartUploadContext) uploadPartsWorker() {\n\tfor block := range ctx.sourceBlocks {\n\t\tbuffer := make([]byte, block.section.Size())\n\t\t_, err := block.section.Read(buffer)\n\t\tif err != nil {\n\t\t\tctx.errChan <- fmt.Errorf(\"error reading source block %d: %w\", block.blockNumber, err)\n\t\t\treturn\n\t\t}\n\t\ttmpLength := int64(len(buffer))\n\t\tsum := md5.Sum(buffer)\n\t\tuploadPartRequest := &objectstorage.UploadPartRequest{\n\t\t\tUploadId:       ctx.multipartUploadResponse.UploadId,\n\t\t\tObjectName:     ctx.multipartUploadResponse.Object,\n\t\t\tNamespaceName:  ctx.multipartUploadResponse.Namespace,\n\t\t\tBucketName:     ctx.multipartUploadResponse.Bucket,\n\t\t\tContentLength:  &tmpLength,\n\t\t\tUploadPartBody: io.NopCloser(bytes.NewReader(buffer)),\n\t\t\tUploadPartNum:  block.blockNumber,\n\t\t\tContentMD5:     common.String(base64.StdEncoding.EncodeToString(sum[:])),\n\t\t\tRequestMetadata: common.RequestMetadata{\n\t\t\t\tRetryPolicy: getDefaultRetryPolicy(),\n\t\t\t},\n\t\t}\n","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/oci/multipart_upload.go#L194-L230","documentation":"Thrown by uploadPartsWorker() when reading from a section reader fails during multipart upload part preparation. The section reader is backed by bytes.NewReader over the in-memory state data, so a read failure is theoretically near-impossible — bytes.NewReader.Read never returns an error for non-nil buffers. This is defensive error handling for an edge case that should not occur under normal conditions.","triggerScenarios":"block.section.Read(buffer) returns a non-nil error. Since block.section is an io.NewSectionReader wrapping bytes.NewReader(m.Data), the only way Read returns an error is if the underlying reader is in an invalid state or buffer allocation produced a nil reader path — both effectively unreachable with well-formed data.","commonSituations":"This error is practically dead code in production. If encountered, it suggests memory corruption, a nil m.Data that somehow passed earlier nil-checks, or a concurrency issue where the underlying data was modified during upload.","solutions":["Check for concurrent modification of the upload data buffer — ensure m.Data is not being mutated during the multipart upload.","Verify memory integrity — this error is not expected under normal Go execution and may indicate a deeper system issue.","Add logging to capture the exact error value and blockNumber to diagnose the unlikely root cause.","If this recurs, the fallback in client.go:147 (single-part upload) should still succeed for sizes <= MaxFilePartSize."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-validate the data buffer before multipart upload\nfunc validateUploadData(data []byte) error {\n    if data == nil {\n        return fmt.Errorf(\"upload data is nil\")\n    }\n    if len(data) == 0 {\n        return fmt.Errorf(\"upload data is empty\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Wrap multipart upload with graceful error handling\nif err := multipartUploadData.multiPartUploadImpl(ctx); err != nil {\n    if strings.Contains(err.Error(), \"error reading source block\") {\n        // Defensive error — log and fall back to single-part upload\n        logger.Warn(\"section read failed, falling back to single-part upload\", \"error\", err)\n        return c.uploadSinglePartObject(ctx, data, sum[:])\n    }\n    return err\n}","preventionTips":["Ensure the data buffer is not concurrently modified during multipart upload operations.","Validate data is non-nil and non-empty before entering the multipart code path.","Leverage the existing fallback to single-part upload in client.go for resilient state writes."],"tags":["oci","multipart-upload","defensive","io"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}