apache/iceberg · warning
Failed to remove dropped properties
Error message
Failed to remove dropped properties {} from replaced view {} What it means
A logged warning emitted when removing legacy/stale properties from a replaced Iceberg view fails to commit. During replaceView, dropped properties are removed via UpdateViewProperties; if that commit throws a RuntimeException, it is logged and swallowed as a best-effort cleanup because view property updates are not atomic with the replace operation yet.
Solutions
- Re-run the REPLACE VIEW statement once the conflicting operation completes so property removal succeeds.
- Check the chained exception for the catalog-side commit error (conflict, permission, rate limit).
- Manually remove the stale properties with ALTER VIEW ... SET/UNSET TBLPROPERTIES if the follow-up keeps failing.
- Retry with fewer concurrent writers to the same view; view property updates are not atomic with replace.
- Upgrade to a version where ViewBuilder supports atomic property removal, eliminating this best-effort path.
Example fix
// before
ALTER VIEW db.v UNSET TBLPROPERTIES ('spark.some.legacy.key'); // manual cleanup needed after warn
// after
-- ensure no concurrent writers, then re-run:
REPLACE VIEW db.v AS SELECT ...; // property removal commits atomically with the new builder API Defensive patterns
Strategy: retry
Validate before calling
// check for concurrent writers before replacing a view
View view = catalog.loadView(TableIdentifier.of("db", "v"));
// ensure no other jobs alter the view concurrently Try / catch
try { update.commit(); } catch (RuntimeException e) { LOG.warn("retry or clean properties manually", e); } Prevention
- Serialize view DDL across jobs
- Remove legacy view properties before connector upgrades
- Retry REPLACE VIEW on commit conflicts
- Upgrade to versions with atomic view property removal
When it happens
Trigger: Calling SparkCatalog.replaceView where the view carries properties that must be dropped (e.g., leftover Spark-specific keys) and the follow-up UpdateViewProperties.commit() fails — typically due to a concurrent modification, catalog commit conflict, or catalog backend error.
Common situations: Concurrent SQL statements modifying the same view; REST/Hive catalog rejecting the property update; legacy views carrying obsolete Spark catalog properties after connector upgrades; commit conflicts from another engine updating the view simultaneously.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Cannot load underlying Iceberg view for view: $ident
- Cannot set reserved property: '$property'
- Altering a view is not supported by catalog:
- Altering a view is not supported by catalog
- Altering a view is not supported by catalog
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e4ecfd43b28049a8.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:757
private void removeDroppedViewProperties(
org.apache.iceberg.view.View view,
Set<String> previousProperties,
Set<String> replacementProperties) {
// Iceberg replacements merge properties, while Spark replacement views carry the complete
// property set. ViewBuilder does not support property removals, so this is a separate retrying
// metadata commit and can fail after the view version has already been replaced.
Set<String> removals = Sets.newHashSet(previousProperties);
removals.removeAll(replacementProperties);
removals.removeAll(ICEBERG_MANAGED_VIEW_PROPERTIES);
removals.removeAll(catalogManagedViewProperties);
if (!removals.isEmpty()) {
UpdateViewProperties update = view.updateProperties();
removals.forEach(update::remove);
try {
update.commit();
} catch (RuntimeException e) {
// TODO: Remove this best-effort follow-up when ViewBuilder supports atomic removals.
LOG.warn(
"Failed to remove dropped properties {} from replaced view {}",
removals,
view.name(),
e);
}
}
}
@Override
public boolean dropView(Identifier ident) {
if (null != asViewCatalog) {
return asViewCatalog.dropView(buildIdentifier(ident));
}
return false;
}
@OverrideView on GitHub (pinned to 86d9c8fc54)