{"record":{"id":"5d20b7694917d883","repo":"hashicorp/terraform","slug":"error-splitting-data-into-parts-s","errorCode":null,"errorMessage":"error splitting data into parts: %s","messagePattern":"error splitting data into parts: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/oci/multipart_upload.go","lineNumber":172,"sourceCode":"\t\tObjectName:         multipartUploadResponse.Object,\n\t\tOpcClientRequestId: multipartUploadResponse.OpcClientRequestId,\n\t\tRequestMetadata:    multipartUploadRequest.RequestMetadata,\n\t\tCommitMultipartUploadDetails: objectstorage.CommitMultipartUploadDetails{\n\t\t\tPartsToCommit: commitMultipartUploadPartDetails,\n\t\t},\n\t}\n\t_, err = multipartUploadData.client.objectStorageClient.CommitMultipartUpload(context.Background(), commitMultipartUploadRequest)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to commit multipart upload: %s\", err)\n\t}\n\n\treturn nil\n}\nfunc (m MultipartUploadData) objectMultiPartSplit() ([]objectStorageSourceBlock, error) {\n\tdataSize := int64(len(m.Data))\n\toffsets, partSize, err := SplitSizeToOffsetsAndLimits(dataSize)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error splitting data into parts: %s\", err)\n\t}\n\tsourceBlocks := make([]objectStorageSourceBlock, len(offsets))\n\tfor i := range offsets {\n\t\tstart := offsets[i]\n\t\tend := start + partSize\n\t\tif end > dataSize {\n\t\t\tend = dataSize\n\t\t}\n\t\tsourceBlocks[i] = objectStorageSourceBlock{\n\t\t\tsection:     io.NewSectionReader(bytes.NewReader(m.Data), start, end-start),\n\t\t\tblockNumber: common.Int(i + 1),\n\t\t}\n\t}\n\treturn sourceBlocks, nil\n}\n\n/*\nSplitSizeToOffsetsAndLimits splits a file size into chunks based on DefaultFilePartSize.","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/oci/multipart_upload.go#L154-L190","documentation":"Thrown by objectMultiPartSplit() in the OCI remote-state backend when SplitSizeToOffsetsAndLimits() fails to divide the state file payload into upload parts. The underlying cause is surfaced via %s, which is typically the 'file exceeds maximum part count' error. This indicates the state data is too large to be chunked within OCI's multipart upload constraints (DefaultFilePartSize=128MB, MaxCount=10000).","triggerScenarios":"Called from client.go:Put() when dataSize > 128MB (DefaultFilePartSize). SplitSizeToOffsetsAndLimits(dataSize) computes totalParts = ceil(dataSize/128MB) and returns an error when totalParts > 10000, i.e. the state file exceeds ~1.28TB. The wrapped error propagates up through multiPartUploadImpl.","commonSituations":"State files are virtually never this large in practice — hitting this means either a corrupted/garbage state blob or a test harness that set DefaultFilePartSize to a very small value (tests set it to 100 bytes) while feeding large data. In production, this error path is nearly unreachable with well-formed state.","solutions":["Investigate why the state file is so large — check for accidental binary blobs, base64-encoded secrets, or corrupted state data.","If running in a test, ensure DefaultFilePartSize is reset to its original 128MB value after the test mutates it, or use smaller test fixtures.","If the state genuinely needs to exceed MaxCount*DefaultFilePartSize, you cannot use this multipart path — consider splitting state across multiple workspaces or reducing state size.","Verify the fallback logic in client.go:147 works — when multipart fails and dataSize <= MaxFilePartSize, it falls back to single-part upload."],"exampleFix":"// In test code, always defer restoration of DefaultFilePartSize:\nDefaultFilePartSize = 100\ndefer func() { DefaultFilePartSize = 128 * 1024 * 1024 }()","handlingStrategy":"validation","validationCode":"// Before uploading state, validate size against multipart constraints\nconst (\n    DefaultFilePartSize int64 = 128 * 1024 * 1024 // 128MB\n    MaxCount            int64 = 10000\n)\n\nfunc validateStateSizeForMultipart(data []byte) error {\n    dataSize := int64(len(data))\n    if dataSize <= DefaultFilePartSize {\n        return nil // single-part upload, no limit concern\n    }\n    totalParts := (dataSize + DefaultFilePartSize - 1) / DefaultFilePartSize\n    if totalParts > MaxCount {\n        return fmt.Errorf(\"state file size %d bytes requires %d parts, exceeding max %d; reduce state size\", dataSize, totalParts, MaxCount)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep Terraform/OpenTofu state files small by splitting large resources into separate workspaces.","Avoid storing binary blobs or base64-encoded large secrets in state — use external secret backends.","In tests, always restore DefaultFilePartSize to its original value after mutation."],"tags":["oci","multipart-upload","state-file","configuration"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}