{"record":{"id":"bbe23e88d1918be6","repo":"apache/beam","slug":"s","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/util/GcsUtilV1.java","lineNumber":1164,"sourceCode":"          // Source and destination are identical. Treat this as a successful rewrite\n          LOG.warn(\n              \"Caught retentionPolicyNotMet error while rewriting to a bucket with retention \"\n                  + \"policy. Skipping because destination {} and source {} are considered identical \"\n                  + \"because their MD5 Hashes are equal.\",\n              getFrom(),\n              getTo());\n\n          if (deleteSource) {\n            readyToEnqueue = true;\n            performDelete = true;\n          } else {\n            readyToEnqueue = false;\n          }\n          lastError = null;\n        } else {\n          // User is attempting to write to a file that hasn't met its retention policy yet.\n          // Not a transient error so likely will not be fixed by a retry\n          throw new IOException(e.getMessage());\n        }\n      } else {\n        lastError = e;\n        readyToEnqueue = true;\n      }\n    }\n  }\n\n  public void copy(Iterable<String> srcFilenames, Iterable<String> destFilenames)\n      throws IOException {\n    rewriteHelper(\n        srcFilenames,\n        destFilenames,\n        /* deleteSource= */ false,\n        /* ignoreMissingSource= */ false,\n        /* ignoreExistingDest= */ false);\n  }\n","sourceCodeStart":1146,"sourceCodeEnd":1182,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/util/GcsUtilV1.java#L1146-L1182","documentation":"During a GCS Rewrite, certain non-transient GoogleStorageExceptions indicate the destination object is under an unmet retention policy (or similar bucket policy condition). The library rethrows the raw exception message as an IOException because retrying will not fix it — the message itself is the error payload.","triggerScenarios":"copy/rewrite to a bucket whose objects have a retention policy that hasn't expired; attempt to overwrite/modify a retention-locked object before its retention period ends.","commonSituations":"Writing into buckets with retention/bucket-lock enabled (e.g. compliance buckets); copying data into a WORM-style bucket before retention allows mutation.","solutions":["Wait until the destination object's retention period expires before rewriting","Write to a different object name/bucket without an active retention hold","Remove or shorten the retention policy if policy allows (requires retention policy unlock permissions)","Inspect e.getMessage() (the original GoogleStorageException) for the exact policy violation"],"exampleFix":"// before\ngcsUtil.copy(src, dest); // IOException: retention policy message\n// after\ntry {\n  gcsUtil.copy(src, dest);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"retention\")) {\n    throw new IllegalStateException(\"Destination under retention policy: \" + e.getMessage(), e);\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"boolean isRetentionBlock(IOException e) {\n  return e.getMessage() != null && e.getMessage().toLowerCase().contains(\"retention\");\n}","tryCatchPattern":"try {\n  gcsUtil.copy(src, dest);\n} catch (IOException e) {\n  if (isRetentionBlock(e)) {\n    // not transient; do not retry — pick new destination or wait out retention\n    throw new IllegalStateException(\"Destination under retention policy\", e);\n  }\n  throw e;\n}","preventionTips":["Check destination bucket retention/bucket-lock config before writing","Use non-retention buckets for scratch/staging data","Do not retry this error — it is non-transient","Read the propagated GoogleStorageException message for the exact policy rule"],"tags":["gcs","retention-policy","copy"],"backgroundTag":"permission-denied","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}