{"record":{"id":"4178b3415cd83fea","repo":"apache/iceberg","slug":"cannot-commit-to-view-s-metadata-location-from-s","errorCode":null,"errorMessage":"Cannot commit to view %s metadata location from %s to %s because it has been concurrently modified to %s","messagePattern":"Cannot commit to view (.+?) metadata location from (.+?) to (.+?) because it has been concurrently modified to (.+?)","errorType":"exception","errorClass":"CommitFailedException","httpStatus":409,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java","lineNumber":524,"sourceCode":"        }\n\n        if (tables.containsKey(identifier)) {\n          throw new AlreadyExistsException(\"Table with same name already exists: %s\", identifier);\n        }\n\n        views.compute(\n            identifier,\n            (k, existingLocation) -> {\n              if (!Objects.equal(existingLocation, oldLocation)) {\n                if (null == base) {\n                  throw new AlreadyExistsException(\"View already exists: %s\", identifier);\n                }\n\n                if (null == existingLocation) {\n                  throw new NoSuchViewException(\"View does not exist: %s\", identifier);\n                }\n\n                throw new CommitFailedException(\n                    \"Cannot commit to view %s metadata location from %s to %s \"\n                        + \"because it has been concurrently modified to %s\",\n                    identifier, oldLocation, newLocation, existingLocation);\n              }\n\n              return newLocation;\n            });\n      }\n    }\n\n    @Override\n    public FileIO io() {\n      return io;\n    }\n\n    @Override\n    protected String viewName() {\n      return fullViewName;","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/inmemory/InMemoryCatalog.java#L506-L542","documentation":"InMemoryCatalog throws this CommitFailedException when a view commit's expected metadata location no longer matches the location currently stored. Another writer modified the view between the read of the old location and the optimistic commit, so the compare-and-swap precondition fails and the commit is rejected for retry.","triggerScenarios":"Two threads or processes call InMemoryCatalog operations like replaceView/updateView on the same view identifier concurrently; the second commit's oldLocation does not equal the view's current stored metadata location.","commonSituations":"Concurrent Spark/Flink jobs or test threads rewriting the same view; a long-running planning phase followed by commit while another client committed first; optimistic-concurrency races in tests that reuse one in-memory catalog across threads.","solutions":["Retry the operation: re-read the view (loadView/loadTable) to get the fresh state, reapply the change, and commit again — CommitFailedException is designed to be retried.","Serialize commits to a given view with application-level locking (e.g., per-identifier lock) if concurrent rewrites are routine.","Check for accidental duplicate jobs or test parallelism writing the same view simultaneously and stagger them."],"exampleFix":"// before\nview.updateSchema().setRequired(1).commit(); // may throw CommitFailedException once\n// after\nRetryUtil.retry(CommitFailedException.class, 3, () -> {\n  View view = catalog.loadView(identifier);\n  view.updateSchema().setRequired(1).commit();\n  return null;\n});","handlingStrategy":"retry","validationCode":"View current = catalog.loadView(identifier); // compare metadata locations before committing\nif (!current.location().equals(expectedLocation)) { /* refresh and reapply */ }","typeGuard":null,"tryCatchPattern":"try {\n  viewOp.commit();\n} catch (CommitFailedException e) {\n  View fresh = catalog.loadView(identifier);\n  // reapply change on fresh state and retry\n}","preventionTips":["Always wrap view commits in a retry loop for CommitFailedException.","Keep read-to-commit windows short to reduce concurrent-modification chances.","Use per-identifier locking when multiple clients routinely rewrite the same view."],"tags":["concurrency","optimistic-locking","catalog","view"],"backgroundTag":"invalid-state-transition","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"}