apache/iceberg · error · UnprocessableEntityException
Invalid namespace update, cannot simultaneously set and remo
Error message
Invalid namespace update, cannot simultaneously set and remove keys: %s
What it means
UpdateNamespacePropertiesRequest.validate() rejects requests whose 'updates' (properties to set) and 'removals' (property names to delete) overlap on the same key. The REST catalog cannot apply both operations to one property at once, so it throws UnprocessableEntityException (HTTP 422) before the request is submitted. This protects servers from ambiguous, order-dependent namespace mutations.
Source
Thrown at core/src/main/java/org/apache/iceberg/rest/requests/UpdateNamespacePropertiesRequest.java:56
private List<String> removals;
private Map<String, String> updates;
public UpdateNamespacePropertiesRequest() {
// Required for Jackson deserialization.
}
private UpdateNamespacePropertiesRequest(List<String> removals, Map<String, String> updates) {
this.removals = removals;
this.updates = updates;
validate();
}
@Override
public void validate() {
Set<String> commonKeys = Sets.intersection(updates().keySet(), Sets.newHashSet(removals()));
if (!commonKeys.isEmpty()) {
throw new UnprocessableEntityException(
"Invalid namespace update, cannot simultaneously set and remove keys: %s", commonKeys);
}
}
public List<String> removals() {
return removals == null ? ImmutableList.of() : removals;
}
public Map<String, String> updates() {
return updates == null ? ImmutableMap.of() : updates;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("removals", removals)
.add("updates", updates)
.toString();View on GitHub (pinned to 86d9c8fc54)
Solutions
- Remove the conflicting key from either the updates map or the removals list before building the request
- Compute removals as the set difference of current keys minus keys you are updating
- Split the change into two sequential requests: first removals, then updates
Example fix
// before
request = UpdateNamespacePropertiesRequest.builder()
.update("owner", "alice")
.remove("owner")
.build();
// after
request = UpdateNamespacePropertiesRequest.builder()
.update("owner", "alice")
.build(); Defensive patterns
Strategy: validation
Validate before calling
Set<String> conflicts = Sets.intersection(updates.keySet(), Sets.newHashSet(removals));
if (!conflicts.isEmpty()) throw new IllegalArgumentException("Conflicting keys: " + conflicts); Try / catch
try { request.validate(); catalog.updateNamespaceProperties(ns, request); } catch (UnprocessableEntityException e) { /* split into two requests */ } Prevention
- Derive removals from current properties minus keys being updated
- Run request.validate() client-side before sending
- Never build removals from stale reads while also setting values
When it happens
Trigger: Building an UpdateNamespacePropertiesRequest where the same key appears in both the update map and the removal list, or client code that computes removals from a stale property list while simultaneously setting new values for those keys.
Common situations: Automation scripts that both rename and set namespace properties; deserialization of malformed client JSON that lists a key in both fields; race conditions where two tools edit the same namespace property concurrently.
Related errors
- Invalid table identifier: %s
- Invalid namespace: %s
- invalid input for namespace %s, error message: %s
- Namespace already exists: %s
- Namespace already exists: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/03ee7a5dca26132d.
Report an issue: GitHub.