{"record":{"id":"442bd8a33da71970","repo":"apache/iceberg","slug":"failed-to-update-view-s-from-catalog-s","errorCode":null,"errorMessage":"Failed to update view %s from catalog %s","messagePattern":"Failed to update view (.+?) from catalog (.+?)","errorType":"exception","errorClass":"CommitFailedException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/jdbc/JdbcViewOperations.java","lineNumber":168,"sourceCode":"    String baseMetadataLocation = base != null ? base.metadataFileLocation() : null;\n\n    if (!Objects.equals(baseMetadataLocation, catalogMetadataLocation)) {\n      throw new CommitFailedException(\n          \"Cannot commit %s: metadata location %s has changed from %s\",\n          viewIdentifier, baseMetadataLocation, catalogMetadataLocation);\n    }\n  }\n\n  private void updateView(String newMetadataLocation, String oldMetadataLocation)\n      throws SQLException, InterruptedException {\n    int updatedRecords =\n        JdbcUtil.updateView(\n            connections, catalogName, viewIdentifier, newMetadataLocation, oldMetadataLocation);\n\n    if (updatedRecords == 1) {\n      LOG.debug(\"Successfully committed to existing view: {}\", viewIdentifier);\n    } else {\n      throw new CommitFailedException(\n          \"Failed to update view %s from catalog %s\", viewIdentifier, catalogName);\n    }\n  }\n\n  private void createView(String newMetadataLocation) throws SQLException, InterruptedException {\n    Namespace namespace = viewIdentifier.namespace();\n    if (PropertyUtil.propertyAsBoolean(catalogProperties, JdbcUtil.STRICT_MODE_PROPERTY, false)\n        && !JdbcUtil.namespaceExists(catalogName, connections, namespace)) {\n      throw new NoSuchNamespaceException(\n          \"Cannot create view %s in catalog %s. Namespace %s does not exist\",\n          viewIdentifier, catalogName, namespace);\n    }\n\n    if (JdbcUtil.tableExists(JdbcUtil.SchemaVersion.V1, catalogName, connections, viewIdentifier)) {\n      throw new AlreadyExistsException(\"Table with same name already exists: %s\", viewIdentifier);\n    }\n\n    if (JdbcUtil.viewExists(catalogName, connections, viewIdentifier)) {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/jdbc/JdbcViewOperations.java#L150-L186","documentation":"updateView performs a conditional UPDATE of the view row (WHERE metadata_location = oldMetadataLocation) and expects exactly 1 updated row. If 0 (or more than 1) rows are updated, a CommitFailedException is thrown, meaning the expected prior state was not found or the update did not match exactly one view.","triggerScenarios":"Concurrent commit changed the metadata location between validateMetadataLocation and the UPDATE; the view row was deleted concurrently; the view row exists under a different catalog_name, so the conditional UPDATE matches nothing.","commonSituations":"Race between two writers committing the same view nearly simultaneously; view dropped by another process mid-commit; duplicated catalog rows from a manually seeded or corrupted catalog table.","solutions":["Refresh the view (viewOps.refresh()) to pick up the new metadata location and retry the commit","Catch CommitFailedException and retry with backoff — this error is designed to be retried after re-reading state","Check for duplicate rows in iceberg_views for the same catalog/namespace/view name and clean them up","Verify the view was not dropped/recreated concurrently by another process","Serialize writers per view or use an external lock if concurrent commits are routine"],"exampleFix":"// before: unconditional retry on same stale object\nops.commit(metadata, base); // fails repeatedly\n// after: refresh between attempts\ntry {\n  ops.commit(metadata, base);\n} catch (CommitFailedException e) {\n  ops.refresh();\n  ops.commit(rebase(metadata), ops.current());\n}","handlingStrategy":"retry","validationCode":"// verify exactly one row exists for this view before updating\nSELECT COUNT(*) FROM iceberg_views\nWHERE catalog_name = ? AND view_namespace = ? AND view_name = ?; // expect 1","typeGuard":null,"tryCatchPattern":"try {\n  viewOps.commit(request);\n} catch (CommitFailedException e) {\n  viewOps.refresh();\n  if (viewOps.current() != null) retryAsUpdate(); else retryAsCreate();\n}","preventionTips":["Refresh and re-apply changes after any CommitFailedException","Detect and clean duplicate rows in iceberg_views","Serialize concurrent writers per view","Confirm the view row uses the same catalog_name as your JdbcCatalog config"],"tags":["optimistic-concurrency","commit-conflict","jdbc","race-condition"],"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"}