googleapis / googleapis/google-cloud-java
[java-storage] Update blob metadata conflict throws a non-retryable StorageException
- Dominant language
- Java
- Stars
- 2.1k
- Forks
- 1.2k
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 157
Description
#### Description
I'm updating the metadata of a blob. When concurrent updates are done, a StorageException is thrown as expected, mentioning a conflict. However, the exception is marked as non-retryable, while the exception message prompts to try again, which is contradictory.
I'd expect the exception to be retryable in that case.
#### Environment details
Using google-cloud-storage 2.52.3 and kotlin 2.0.0
#### Steps to reproduce
1. Try updating the metadata of a blob in 2 concurrent processes
#### Code example
```kotlin
storage
.get(blobId)
.toBuilder()
.setMetadata(
mapOf(
"MyKey" to "MyValue"
)
).build()
.update()
```
#### Stack trace
```
com.google.cloud.storage.StorageException: The metadata for object "path/to/my/blob" was edited during the operation. Please try again.
at com.google.cloud.storage.StorageException.translate(StorageException.java:230)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.translate(HttpStorageRpc.java:360)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.patch(HttpStorageRpc.java:719)
at com.google.cloud.storage.StorageImpl.lambda$update$19(StorageImpl.java:609)
at com.google.cloud.storage.Retrying$DefaultRetrier.run(Retrying.java:165)
at com.google.cloud.storage.Retrying$HttpRetrier.run(Retrying.java:206)
at com.google.cloud.storage.StorageImpl.run(StorageImpl.java:1619)
at com.google.cloud.storage.StorageImpl.update(StorageImpl.java:607)
at com.google.cloud.storage.Blob.update(Blob.java:865)
Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 409 Conflict
POST https://storage.googleapis.com/storage/v1/b/my-bucket/o/path%2Fto%2Fmy%2Fblob?projection=full
{
"code" : 409,
"errors" : [ {
"domain" : "global",
"message" : "The metadata for object \"path/to/my/blob\" was edited during the operation. Please try again.",
"reason" : "conflict"
} ],
"message" : "The metadata for object \"path/to/my/blob\" was edited during the operation. Please try again."
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:118)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:37)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$3.interceptResponse(AbstractGoogleClientRequest.java:479)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1111)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:565)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:506)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:616)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.patch(HttpStorageRpc.java:716)
... 28 common frames omitted
```
Following these steps guarantees the quickest resolution possible.
Thanks!
Contributor guide
Research direction
Start by reading StorageException.java around translate, then follow the 409 conflict through HttpStorageRpc.java and StorageImpl.java as shown in the stack trace. Done means this conflict is classified as retryable consistently with its message telling callers to try again, with regression coverage for the path if existing tests expose it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- gcp, google-cloud, java
- Domain
- api, cloud
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100