{"record":{"id":"0292f3b59e82f7a7","repo":"OtterMind/Chat2DB","slug":"database-delete-systemdatabaseforbidden","errorCode":"database.delete.systemDatabaseForbidden","errorMessage":"database.delete.systemDatabaseForbidden","messagePattern":"database\\.delete\\.systemDatabaseForbidden","errorType":"validation","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbDatabaseObjectDeleteServiceImpl.java","lineNumber":187,"sourceCode":"    private String requireName(String name, String fieldName) {\n        String trimmed = StringUtils.trimToNull(name);\n        if (trimmed == null) {\n            throw new BusinessException(\"database.delete.\" + fieldName + \"Required\");\n        }\n        return trimmed;\n    }\n\n    private void assertDatabaseDeletionSupported(String dbType) {\n        DBConfig dbConfig = Chat2DBContext.getDBConfig(dbType);\n        if (dbConfig == null || !dbConfig.isSupportDatabase()) {\n            throw new BusinessException(\"database.delete.notSupportDatabase\");\n        }\n    }\n\n    private void rejectSystemDatabase(String dbType, String databaseName) {\n        if (DatabaseTypeEnum.MYSQL.name().equalsIgnoreCase(dbType)\n                && MYSQL_SYSTEM_DATABASES.contains(StringUtils.lowerCase(databaseName))) {\n            throw new BusinessException(\"database.delete.systemDatabaseForbidden\");\n        }\n        if (DatabaseTypeEnum.POSTGRESQL.name().equalsIgnoreCase(dbType)\n                && POSTGRESQL_SYSTEM_DATABASES.contains(StringUtils.lowerCase(databaseName))) {\n            throw new BusinessException(\"database.delete.systemDatabaseForbidden\");\n        }\n    }\n\n    private Connection requireConnection() {\n        Connection connection = Chat2DBContext.getConnection();\n        if (connection == null) {\n            throw new BusinessException(\"database.delete.connectionFailed\");\n        }\n        return connection;\n    }\n\n    private void assertDatabaseExists(Connection connection, String dbType, String databaseName) {\n        List<Database> databases = Chat2DBContext.getDbMetaData(dbType).databases(connection);\n        boolean exists = databases != null && databases.stream()","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbDatabaseObjectDeleteServiceImpl.java#L169-L205","documentation":"Thrown by rejectSystemDatabase when the active dbType is MySQL and the target database name matches one of the protected system databases: information_schema, mysql, performance_schema, sys (case-insensitive). This is a hard safety guard preventing destructive DROP on MySQL's internal catalogs. It fires in both prepare and execute phases.","triggerScenarios":"Calling prepareDatabaseDelete or executeDatabaseDelete with databaseName equal to (case-insensitive) 'information_schema', 'mysql', 'performance_schema', or 'sys' while the connection's dbType is MySQL.","commonSituations":"User types a system database name in the delete-confirmation dialog; a scripted bulk-cleanup that iterates all database names without filtering system catalogs; UI listing databases and letting the user pick 'mysql'.","solutions":["Do not attempt to delete MySQL system databases; exclude information_schema, mysql, performance_schema, and sys from any batch operation.","Filter the database list in the UI before offering the delete action so system databases are not selectable.","If a custom database legitimately shares a system name, rename it before deleting."],"exampleFix":"// before\nprepareDatabaseDelete(req); // databaseName='mysql'\n\n// after\nSet<String> blocked = Set.of(\"information_schema\",\"mysql\",\"performance_schema\",\"sys\");\nif (blocked.contains(StringUtils.lowerCase(req.getDatabaseName()))) {\n    return; // skip system databases\n}\nprepareDatabaseDelete(req);","handlingStrategy":"validation","validationCode":"Set<String> mysqlBlocked = Set.of(\"information_schema\",\"mysql\",\"performance_schema\",\"sys\");\nif (\"MYSQL\".equalsIgnoreCase(dbType) && mysqlBlocked.contains(StringUtils.lowerCase(databaseName))) {\n    // skip / disable delete\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter MySQL system databases out of the deletable list in the UI.","Maintain a deny-list constant on the client matching the server's MYSQL_SYSTEM_DATABASES set."],"tags":["database-delete","system-database","mysql","safety-guard"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}