{"record":{"id":"4193a9503962bc27","repo":"apache/iceberg","slug":"cannot-drop-namespace-s-because-it-still-contains","errorCode":null,"errorMessage":"Cannot drop namespace %s because it still contains Iceberg tables","messagePattern":"Cannot drop namespace (.+?) because it still contains Iceberg tables","errorType":"exception","errorClass":"NamespaceNotEmptyException","httpStatus":null,"severity":"error","filePath":"aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java","lineNumber":571,"sourceCode":"  }\n\n  @Override\n  public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyException {\n    namespaceExists(namespace);\n\n    GetTablesResponse response =\n        glue.getTables(\n            GetTablesRequest.builder()\n                .catalogId(awsProperties.glueCatalogId())\n                .databaseName(\n                    IcebergToGlueConverter.toDatabaseName(\n                        namespace, awsProperties.glueCatalogSkipNameValidation()))\n                .build());\n\n    if (response.hasTableList() && !response.tableList().isEmpty()) {\n      Table table = response.tableList().get(0);\n      if (isGlueIcebergTable(table)) {\n        throw new NamespaceNotEmptyException(\n            \"Cannot drop namespace %s because it still contains Iceberg tables\", namespace);\n      } else {\n        throw new NamespaceNotEmptyException(\n            \"Cannot drop namespace %s because it still contains non-Iceberg tables\", namespace);\n      }\n    }\n\n    glue.deleteDatabase(\n        DeleteDatabaseRequest.builder()\n            .catalogId(awsProperties.glueCatalogId())\n            .name(\n                IcebergToGlueConverter.toDatabaseName(\n                    namespace, awsProperties.glueCatalogSkipNameValidation()))\n            .build());\n    LOG.info(\"Dropped namespace: {}\", namespace);\n    // Always successful, otherwise exception is thrown\n    return true;\n  }","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java#L553-L589","documentation":"GlueCatalog.dropNamespace throws NamespaceNotEmptyException when Glue's GetTables for the database returns at least one table whose parameters identify it as an Iceberg table. Iceberg refuses to drop a namespace that still contains Iceberg tables to prevent silent data loss.","triggerScenarios":"Calling catalog.dropNamespace(ns) while the Glue database still contains Iceberg tables registered with metadata_location parameters.","commonSituations":"Cleanup scripts dropping databases without listing tables first; partial pipeline teardowns that deleted some but not all tables; forgetting that views/tables created by other engines in the same database block the drop.","solutions":["Drop all Iceberg tables first: iterate catalog.listTables(ns) and call dropTable on each, then drop the namespace.","Use dropTable(table, true) purge carefully only if the underlying data should also be deleted.","If tables were already removed from Iceberg but stale entries remain in Glue, delete the orphan Glue table entries via the AWS console/API.","Confirm you are dropping the intended database — the non-empty check may be catching a live production database."],"exampleFix":"// before\ncatalog.dropNamespace(Namespace.of(\"staging\"));\n\n// after\nNamespace ns = Namespace.of(\"staging\");\nfor (TableIdentifier t : catalog.listTables(ns)) {\n  catalog.dropTable(t);\n}\ncatalog.dropNamespace(ns);","handlingStrategy":"validation","validationCode":"Namespace ns = Namespace.of(\"staging\");\nif (!catalog.listTables(ns).isEmpty()) {\n  throw new IllegalStateException(\"Namespace \" + ns + \" still has tables; drop them first\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  catalog.dropNamespace(ns);\n} catch (NamespaceNotEmptyException e) {\n  catalog.listTables(ns).forEach(catalog::dropTable);\n  catalog.dropNamespace(ns);\n}","preventionTips":["Enumerate and drop all tables before dropping a namespace","Run teardown scripts that empty namespaces in order: tables then namespaces","Use dedicated databases per pipeline so cleanup scope is obvious"],"tags":["aws","glue","namespace","not-empty","drop"],"backgroundTag":"namespace-not-empty","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"}