{"record":{"id":"0772503a92e4972f","repo":"apache/iceberg","slug":"cannot-commit-s-because-base-metadata-location","errorCode":null,"errorMessage":"Cannot commit %s because base metadata location '%s' is not same as the current DynamoDb location '%s'","messagePattern":"Cannot commit (.+?) because base metadata location '(.+?)' is not same as the current DynamoDb location '(.+?)'","errorType":"exception","errorClass":"CommitFailedException","httpStatus":null,"severity":"error","filePath":"aws/src/main/java/org/apache/iceberg/aws/dynamodb/DynamoDbTableOperations.java","lineNumber":169,"sourceCode":"          throw new CommitStateUnknownException(persistFailure);\n      }\n    } finally {\n      try {\n        if (commitStatus == CommitStatus.FAILURE) {\n          // if anything went wrong, clean up the uncommitted metadata file\n          io().deleteFile(newMetadataLocation);\n        }\n      } catch (RuntimeException e) {\n        LOG.error(\"Failed to cleanup metadata file at {}\", newMetadataLocation, e);\n      }\n    }\n  }\n\n  private void checkMetadataLocation(GetItemResponse table, TableMetadata base) {\n    String dynamoMetadataLocation = table.hasItem() ? getMetadataLocation(table) : null;\n    String baseMetadataLocation = base != null ? base.metadataFileLocation() : null;\n    if (!Objects.equals(baseMetadataLocation, dynamoMetadataLocation)) {\n      throw new CommitFailedException(\n          \"Cannot commit %s because base metadata location '%s' is not same as the current DynamoDb location '%s'\",\n          tableName(), baseMetadataLocation, dynamoMetadataLocation);\n    }\n  }\n\n  private String getMetadataLocation(GetItemResponse table) {\n    return table.item().get(DynamoDbCatalog.toPropertyCol(METADATA_LOCATION_PROP)).s();\n  }\n\n  private Map<String, String> prepareProperties(\n      GetItemResponse response, String newMetadataLocation) {\n    Map<String, String> properties =\n        response.hasItem() ? getProperties(response) : Maps.newHashMap();\n    properties.put(TABLE_TYPE_PROP, ICEBERG_TABLE_TYPE_VALUE.toUpperCase(Locale.ROOT));\n    properties.put(METADATA_LOCATION_PROP, newMetadataLocation);\n    if (currentMetadataLocation() != null && !currentMetadataLocation().isEmpty()) {\n      properties.put(PREVIOUS_METADATA_LOCATION_PROP, currentMetadataLocation());\n    }","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/aws/src/main/java/org/apache/iceberg/aws/dynamodb/DynamoDbTableOperations.java#L151-L187","documentation":"CommitFailedException thrown by checkMetadataLocation when the TableMetadata base the client committed from has a metadataFileLocation different from the metadata location currently stored in DynamoDB. This is optimistic-concurrency validation: the table was changed by someone else after this client's refresh.","triggerScenarios":"doCommit fetches the current Dynamo item and compares its COL_METADATA_LOCATION against the client's base metadata; a mismatch throws.","commonSituations":"Another writer committed between this client's loadTable/refresh and its commit; a long batch job holding stale metadata; a concurrent compaction or expireSnapshots job.","solutions":["Refresh the table (re-read latest metadata) and reapply/redo the operation, then commit again","Use row-level conflict detection/merge for overlapping writes","Coordinate concurrent writers with a lock (e.g. DynamoDbLockManager) to serialize commits"],"exampleFix":"// before\nTable t = catalog.loadTable(id);\n// long-running work, others commit meanwhile\nt.updateSchema().addColumn(\"c\", Types.StringType.get()).commit(); // fails\n// after\nTable t = catalog.loadTable(id);\n// ... long work ...\nt.refresh(); // rebase before committing\nt.updateSchema().addColumn(\"c\", Types.StringType.get()).commit();","handlingStrategy":"retry","validationCode":"table.refresh(); // ensure base metadata is current before any commit","typeGuard":null,"tryCatchPattern":"try {\n  table.updateSchema().addColumn(\"c\", Types.StringType.get()).commit();\n} catch (CommitFailedException e) {\n  table.refresh(); // rebase and retry\n  table.updateSchema().addColumn(\"c\", Types.StringType.get()).commit();\n}","preventionTips":["Refresh right before commit in long-running jobs","Minimize time between load and commit","Coordinate concurrent writers with locks; check base-vs-current metadata before committing"],"tags":["aws","dynamodb","concurrency","metadata-mismatch"],"backgroundTag":"commit-conflict","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}