{"record":{"id":"bc274ee4daac14bd","repo":"apache/iceberg","slug":"cannot-commit-to-table-s-metadata-location-from","errorCode":null,"errorMessage":"Cannot commit to table %s metadata location from %s to %s because it has been concurrently modified to %s","messagePattern":"Cannot commit to table (.+?) metadata location from (.+?) to (.+?) because it has been concurrently modified to (.+?)","errorType":"exception","errorClass":"CommitFailedException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java","lineNumber":454,"sourceCode":"\n        if (views.containsKey(tableIdentifier)) {\n          throw new AlreadyExistsException(\n              \"View with same name already exists: %s\", tableIdentifier);\n        }\n\n        tables.compute(\n            tableIdentifier,\n            (k, existingLocation) -> {\n              if (!Objects.equal(existingLocation, oldLocation)) {\n                if (null == base) {\n                  throw new AlreadyExistsException(\"Table already exists: %s\", tableName());\n                }\n\n                if (null == existingLocation) {\n                  throw new NoSuchTableException(\"Table does not exist: %s\", tableName());\n                }\n\n                throw new CommitFailedException(\n                    \"Cannot commit to table %s metadata location from %s to %s \"\n                        + \"because it has been concurrently modified to %s\",\n                    tableIdentifier, oldLocation, newLocation, existingLocation);\n              }\n              return newLocation;\n            });\n      }\n    }\n\n    @Override\n    public FileIO io() {\n      return fileIO;\n    }\n\n    @Override\n    protected String tableName() {\n      return fullTableName;\n    }","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java#L436-L472","documentation":"This is the optimistic-concurrency conflict of the in-memory catalog: the commit expected the table's metadata location to equal oldLocation, but the map holds a different existingLocation, meaning another committer advanced the table in between. Per Iceberg's commit contract, CommitFailedException signals the caller to refresh and retry the update against the new state.","triggerScenarios":"Two writers load the same table and both call commit(); the loser sees existingLocation != oldLocation and neither base nor existingLocation is null. Any concurrent metadata operation (schema update, append, partition spec change) on the same table.","commonSituations":"Multiple executors/threads appending to one table; concurrent schema evolution and writes; retry loops that do not refresh the table before recommitting.","solutions":["Retry the commit: catch CommitFailedException, call table.refresh(), re-apply the update, and commit again (Iceberg's RetryUtil/Tasks.foreach with retry works well).","Reduce conflict windows by shortening transaction scopes or partitioning work across distinct tables.","Ensure every retry reloads/refreshes metadata; never reuse stale TableMetadata."],"exampleFix":"// before\ntable.updateSchema().addColumn(\"c\", Types.IntegerType.get()).commit();\n\n// after\nTasks.foreach(table)\n    .retry(3)\n    .onlyOn(CommitFailedException.class)\n    .run(t -> t.refresh());\ntable.refresh();\ntable.updateSchema().addColumn(\"c\", Types.IntegerType.get()).commit();","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { table.commit(update); } catch (CommitFailedException e) { table.refresh(); /* re-apply update on refreshed metadata and retry, bounded attempts */ }","preventionTips":["Always refresh() the table before reapplying a failed commit","Use Tasks.foreach(...).retry(n).onlyOn(CommitFailedException.class) for commits","Keep transactions short to shrink conflict windows","Partition concurrent writers across distinct tables/partitions"],"tags":["catalog","concurrency","optimistic-locking","commit-conflict"],"backgroundTag":"concurrent-modification","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}