hashicorp/terraform · error

failed to upload part %d: %w

Error message

failed to upload part %d: %w

What it means

Thrown by a worker goroutine inside multiPartUploadImpl when the OCI object storage UploadPart API call fails for a single chunk of a multipart upload. The %d is the 1-based part number and %w wraps the underlying SDK/network error. Because up to 10 concurrent workers run, one failing part aborts the whole upload via the worker returning early on the error channel.

Source

Thrown at internal/backend/remote-state/oci/multipart_upload.go:241

			UploadPartBody: io.NopCloser(bytes.NewReader(buffer)),
			UploadPartNum:  block.blockNumber,
			ContentMD5:     common.String(base64.StdEncoding.EncodeToString(sum[:])),
			RequestMetadata: common.RequestMetadata{
				RetryPolicy: getDefaultRetryPolicy(),
			},
		}

		if ctx.client.kmsKeyID != "" {
			uploadPartRequest.OpcSseKmsKeyId = common.String(ctx.client.kmsKeyID)
		} else if ctx.client.SSECustomerKey != "" && ctx.client.SSECustomerKeySHA256 != "" {
			uploadPartRequest.OpcSseCustomerKey = common.String(ctx.client.SSECustomerKey)
			uploadPartRequest.OpcSseCustomerKeySha256 = common.String(ctx.client.SSECustomerKeySHA256)
			uploadPartRequest.OpcSseCustomerAlgorithm = common.String(ctx.client.SSECustomerAlgorithm)
		}

		response, err := ctx.client.objectStorageClient.UploadPart(context.Background(), *uploadPartRequest)
		if err != nil {
			ctx.errChan <- fmt.Errorf("failed to upload part %d: %w", *block.blockNumber, err)
			return
		}
		ctx.osUploadPartResponses <- objectStorageUploadPartResponse{
			response:   response,
			error:      nil,
			partNumber: block.blockNumber,
		}
		ctx.wg.Done()

	}
}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Inspect the wrapped error (the %w) — it is the real cause; fix that (auth, network, KMS key) before retrying.
  2. Verify the SSE settings: if the bucket uses a customer-provided key, ensure SSECustomerKey, SSECustomerKeySHA256 and SSECustomerAlgorithm are all set and consistent, or use kmsKeyId instead.
  3. Confirm the OCI credentials/region in the config are still valid and the namespace/bucket names are correct.
  4. Retry the operation on a stable network; the per-part request already carries getDefaultRetryPolicy() so transient blips are retried automatically — a surfaced error means retries were exhausted.
  5. If the file is near the 10000-part / 50GB-part limits, raise DefaultFilePartSize via the OSS client if the data is huge.

Example fix

// before: mismatched SSE config
client.SSECustomerKey = key
// SSECustomerKeySHA256 left unset -> part upload fails

// after: provide the SHA256 (base64 of the raw key hash) consistently
client.SSECustomerKey = key
client.SSECustomerKeySHA256 = base64.StdEncoding.EncodeToString(sha256sum)
client.SSECustomerAlgorithm = "AES256"
Defensive patterns

Strategy: retry

Validate before calling

// Before launching a large upload, confirm creds + SSE config are consistent.
func validateOCIClient(c *RemoteClient) error {
    if c.bucketName == "" || c.namespace == "" {
        return fmt.Errorf("oci client missing bucket/namespace")
    }
    if (c.SSECustomerKey != "") != (c.SSECustomerKeySHA256 != "") {
        return fmt.Errorf("SSE-C requires both SSECustomerKey and SSECustomerKeySHA256")
    }
    return nil
}

Try / catch

// Wrap multiPartUploadImpl; surface the wrapped part error, retry idempotently.
err := uploadData.multiPartUploadImpl(ctx)
if err != nil && strings.Contains(err.Error(), "failed to upload part") {
    // part uploads are idempotent (ContentMD5 set); safe to retry the whole upload
    return uploadData.multiPartUploadImpl(ctx)
}

Prevention

When it happens

Trigger: A call to multiPartUploadImpl whose source data exceeds 128MB (DefaultFilePartSize) so it is split into parts; UploadPart (oci objectstorage) returns a non-nil error for one chunk. Causes: expired STS/OAuth token, SSE-KMS/SSE-C key mismatch on a part, network reset mid-stream, bucket not found, quota/rate-limit, or ContentMD5 mismatch detected server-side.

Common situations: Running terraform init/apply with the oci backend on a large state file over an unstable link; rotating OCI credentials mid-run; specifying an SSECustomerKey that does not match the bucket's server-side encryption config; exceeding the object-storage request rate limit on a shared tenancy.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/fc371d6669bdfdfd. Report an issue: GitHub.