{"record":{"id":"1c5d74141837f4d4","repo":"OtterMind/Chat2DB","slug":"database-delete-systemschemaforbidden","errorCode":"database.delete.systemSchemaForbidden","errorMessage":"database.delete.systemSchemaForbidden","messagePattern":"database\\.delete\\.systemSchemaForbidden","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":244,"sourceCode":"    private String buildDropDatabase(String dbType, String databaseName) {\n        return Chat2DBContext.getDbMetaData(dbType).getSqlBuilder().ddl().database().buildDropDatabase(databaseName);\n    }\n\n    private void assertSchemaDeletionSupported(String dbType) {\n        DBConfig dbConfig = Chat2DBContext.getDBConfig(dbType);\n        if (dbConfig == null || !dbConfig.isSupportSchema()\n                || !DatabaseTypeEnum.POSTGRESQL.name().equalsIgnoreCase(dbType)) {\n            throw new BusinessException(\"database.delete.notSupportSchema\");\n        }\n    }\n\n    private void rejectSystemSchema(String dbType, String schemaName) {\n        if (DatabaseTypeEnum.POSTGRESQL.name().equalsIgnoreCase(dbType)) {\n            String lowerSchemaName = StringUtils.lowerCase(schemaName);\n            if (POSTGRESQL_SYSTEM_SCHEMAS.contains(lowerSchemaName)\n                    || StringUtils.startsWith(lowerSchemaName, \"pg_toast\")\n                    || StringUtils.startsWith(lowerSchemaName, \"pg_temp\")) {\n                throw new BusinessException(\"database.delete.systemSchemaForbidden\");\n            }\n        }\n    }\n\n    private void assertSchemaExists(Connection connection, String databaseName, String schemaName) {\n        List<Schema> schemas = Chat2DBContext.getDbMetaData().schemas(connection, databaseName);\n        boolean exists = schemas != null && schemas.stream()\n                .anyMatch(schema -> StringUtils.equals(schema.getName(), schemaName));\n        if (!exists) {\n            throw new BusinessException(\"database.delete.schemaNotExists\");\n        }\n    }\n\n    private String schemaConfirmName(String schemaName) {\n        return schemaName;\n    }\n\n    private String buildDropSchema(String dbType, String schemaName) {","sourceCodeStart":226,"sourceCodeEnd":262,"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#L226-L262","documentation":"Thrown by rejectSystemSchema when the active dbType is PostgreSQL and the schema name matches a protected system schema (pg_catalog, information_schema, public) or starts with pg_toast or pg_temp (case-insensitive). These schemas are internal to PostgreSQL and dropping them corrupts the database. Fires in both prepare and execute paths.","triggerScenarios":"Calling prepareSchemaDelete or executeSchemaDelete with schemaName equal to (case-insensitive) 'pg_catalog', 'information_schema', or 'public', or starting with 'pg_toast'/'pg_temp' on a PostgreSQL connection.","commonSituations":"User selects 'public' in the schema list and attempts delete; temp schema (pg_temp_N) appears in listings; pg_toast schemas leaked into UI.","solutions":["Never target pg_catalog, information_schema, public, pg_toast*, or pg_temp* for deletion.","Filter these names from the schema list before presenting delete as an option.","Create and delete only user-defined schemas."],"exampleFix":"// before\nprepareSchemaDelete(req); // schemaName='public'\n\n// after\nSet<String> blocked = Set.of(\"pg_catalog\",\"information_schema\",\"public\");\nString lower = StringUtils.lowerCase(req.getSchemaName());\nif (blocked.contains(lower) || lower.startsWith(\"pg_toast\") || lower.startsWith(\"pg_temp\")) {\n    return; // skip system schemas\n}\nprepareSchemaDelete(req);","handlingStrategy":"validation","validationCode":"Set<String> pgSchemas = Set.of(\"pg_catalog\",\"information_schema\",\"public\");\nString lower = StringUtils.lowerCase(schemaName);\nif (\"POSTGRESQL\".equalsIgnoreCase(dbType)\n        && (pgSchemas.contains(lower) || lower.startsWith(\"pg_toast\") || lower.startsWith(\"pg_temp\"))) {\n    // skip / disable delete\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter system and temp schemas from the deletable schema list.","Maintain a deny-list matching POSTGRESQL_SYSTEM_SCHEMAS plus the pg_toast/pg_temp prefixes."],"tags":["schema-delete","system-schema","postgresql","safety-guard"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}