apache/iceberg · error · UncheckedIOException
Cannot drop namespace '%s': %s
Error message
Cannot drop namespace '%s': %s
What it means
Fallback handler in dropNamespace: when a NessieReferenceConflictException carries an unrecognized conflict (or multiple/unextractable conflicts), it is rethrown as UncheckedIOException 'Cannot drop namespace X: <server message>'. The server rejected the delete commit for a reason the client does not specially classify.
Source
Thrown at nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java:352
commitRetry("drop namespace " + key, Operation.Delete.of(key));
return true;
} catch (NessieReferenceConflictException e) {
Optional<Conflict> conflict =
NessieUtil.extractSingleConflict(
e,
EnumSet.of(
Conflict.ConflictType.KEY_DOES_NOT_EXIST,
Conflict.ConflictType.NAMESPACE_NOT_EMPTY));
if (conflict.isPresent()) {
Conflict.ConflictType conflictType = conflict.get().conflictType();
switch (conflictType) {
case KEY_DOES_NOT_EXIST:
return false;
case NAMESPACE_NOT_EMPTY:
throw new NamespaceNotEmptyException(e, "Namespace '%s' is not empty.", namespace);
}
}
throw new UncheckedIOException(
String.format("Cannot drop namespace '%s': %s", namespace, e.getMessage()), e);
}
} catch (NessieNotFoundException e) {
LOG.error(
"Cannot drop namespace '{}': ref '{}' is no longer valid.",
namespace,
getRef().getName(),
e);
} catch (BaseNessieClientServerException e) {
throw new UncheckedIOException(
String.format("Cannot drop namespace '%s': %s", namespace, e.getMessage()), e);
}
return false;
}
private static void checkNamespaceIsValid(Namespace namespace) {
if (namespace.isEmpty()) {
throw new NoSuchNamespaceException("Invalid namespace: %s", namespace);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the wrapped cause (NessieReferenceConflictException) and server message for the actual conflict.
- Retry the drop after concurrent operations on the ref settle.
- Upgrade iceberg-nessie to a client version matching your Nessie server.
- Update ref contents via the Nessie API directly if the conflict needs manual resolution.
Example fix
// before
catalog.dropNamespace(ns); // UncheckedIOException on unknown conflict
// after
try {
catalog.dropNamespace(ns);
} catch (UncheckedIOException e) {
LOG.warn("drop conflict: {}", e.getCause(), e);
// re-inspect ref state, then retry
} Defensive patterns
Strategy: retry
Validate before calling
// minimize race window: re-read ref state immediately before drop Content c = api.getContent().reference(ref).key(key).get().get(key);
Try / catch
try {
return catalog.dropNamespace(ns);
} catch (UncheckedIOException e) {
if (e.getCause() instanceof NessieReferenceConflictException && attempt < 3) {
return dropNamespaceWithRetry(ns, attempt + 1); // bounded retry after conflict
}
throw e;
} Prevention
- Serialize namespace DDL on a ref (avoid parallel drop/create on same keys).
- Keep client and server versions current so all conflict types are recognized.
- Log the full cause chain for unclassified conflicts.
When it happens
Trigger: Calling dropNamespace when the server returns a conflict type other than KEY_DOES_NOT_EXIST or NAMESPACE_NOT_EMPTY (e.g. unexpected concurrent mutation, server-side validation conflicts).
Common situations: Heavy concurrent commits on the same ref; Nessie server version emitting new conflict types unknown to the client.
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 create namespace '%s': %s
- Cannot update properties on namespace '%s': %s
- Cannot create namespace '%s': parent namespace '%s' does not
- Namespace '%s' is not empty.
- Namespace already exists: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/a70bfa8e1388e8c6.
Report an issue: GitHub.