apache/iceberg · error · UnsupportedOperationException
Cannot unset reserved property
Error message
Cannot unset reserved property: '%s'
What it means
SparkCatalog.alterView rejects ViewChange.RemoveProperty (and SetProperty) changes whose property name is in SparkView.RESERVED_PROPERTIES (e.g. query, schema, dialect, queryColumnNames managed by Iceberg). verifyNonReservedProperty (SparkCatalog.java:725) throws UnsupportedOperationException with 'Cannot unset reserved property: <name>' because those properties are derived from the view definition and must never be edited directly.
Solutions
- Remove the reserved key from your UNSET list; reserved properties are managed by the engine and cannot be changed via ALTER VIEW.
- To change 'query' or 'schema', redefine the view with CREATE OR REPLACE VIEW instead of altering properties.
- Filter properties client-side against SparkView.RESERVED_PROPERTIES before issuing alterView.
- Store custom metadata under a non-reserved, prefixed key (e.g. 'custom.owner') and unset that instead.
Example fix
// before
spark.sql("ALTER VIEW analytics.v UNSET TBLPROPERTIES ('query')"); // UnsupportedOperationException
// after
spark.sql("ALTER VIEW analytics.v UNSET TBLPROPERTIES ('custom.owner')");
// redefine reserved metadata instead:
spark.sql("CREATE OR REPLACE VIEW analytics.v AS SELECT ..."); Defensive patterns
Strategy: validation
Validate before calling
Set<String> reserved = SparkView.RESERVED_PROPERTIES;
List<String> safeKeys = propsToUnset.stream()
.filter(k -> !reserved.contains(k))
.collect(Collectors.toList());
// only issue UNSET for safeKeys Type guard
boolean isUnsettable(String property) {
return !SparkView.RESERVED_PROPERTIES.contains(property);
} Try / catch
try {
viewChangeRemover.apply(ident, properties);
} catch (UnsupportedOperationException e) {
if (e.getMessage().startsWith("Cannot unset reserved property")) {
// skip the reserved key and continue with the remaining properties
}
} Prevention
- Filter property lists against SparkView.RESERVED_PROPERTIES before UNSET/SET.
- Never blind-UNSET all properties in cleanup scripts; whitelist removable keys.
- To change reserved metadata (query/schema/dialect), use CREATE OR REPLACE VIEW instead of ALTER.
- Prefix custom metadata keys (e.g. 'custom.') so they can never collide with reserved names.
When it happens
Trigger: Calling ALTER VIEW <ident> UNSET TBLPROPERTIES ('query') or the programmatic equivalent alterView(ident, new ViewChange.RemoveProperty("query")) — likewise for 'schema', 'dialect', 'description-of-query columns' such as SparkView.QUERY_COLUMN_NAMES — where the property matches a reserved name in SparkView.RESERVED_PROPERTIES.
Common situations: Cleanup scripts that iterate all TBLPROPERTIES and UNSET each one, blindly hitting reserved keys; migrating views from Hive where 'query'/'schema' were user-settable; templated UNSET commands with a hardcoded property list that includes reserved names.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Altering a view is not supported by catalog: catalogName
- Cannot unset reserved property
- Cannot unset reserved property
- Creating a view is not supported by catalog: catalogName
- Namespace does not exist: currentNamespace
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/b50529bddc07a55b.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/SparkCatalog.java:727
updateViewProperties.remove(remove.property());
}
}
updateViewProperties.commit();
return new SparkView(catalogName, view);
} catch (org.apache.iceberg.exceptions.NoSuchViewException e) {
throw new NoSuchViewException(ident);
}
}
throw new UnsupportedOperationException(
"Altering a view is not supported by catalog: " + catalogName);
}
private static void verifyNonReservedProperty(String property, String errorMsg) {
if (SparkView.RESERVED_PROPERTIES.contains(property)) {
throw new UnsupportedOperationException(String.format(errorMsg, property));
}
}
private static void verifyNonReservedPropertyIsUnset(String property) {
verifyNonReservedProperty(property, "Cannot unset reserved property: '%s'");
}
private static void verifyNonReservedPropertyIsSet(String property) {
verifyNonReservedProperty(property, "Cannot set reserved property: '%s'");
}
@Override
public boolean dropView(Identifier ident) {
if (null != asViewCatalog) {
return asViewCatalog.dropView(buildIdentifier(ident));
}
return false;View on GitHub (pinned to 86d9c8fc54)