OtterMind/Chat2DB · error · BusinessException

routine.operation.databaseRequired

routine.operation.databaseRequired

Error message

routine.operation.databaseRequired

What it means

Thrown by requireDatabaseName when operation.getDatabaseName(), after trim, is blank. The database name is required so the routine can be qualified as `database`.`routine` in DROP/CREATE/CALL statements and so parameter metadata can be scoped. Without it the SQL would be ambiguous or fail.

Solutions

  1. Set operation.setDatabaseName(currentDatabase) from the connection's catalog before invoking.
  2. Validate databaseName is non-blank at the request boundary.
  3. If the operation originates from a tree node, ensure the node carries and forwards its database.
  4. Fall back to connection.getCatalog() when the operation omits the database, after confirming it is non-null.

Example fix

// before
routineManager.previewInvocation(connection, operation);

// after
if (StringUtils.isBlank(operation.getDatabaseName())) {
    String catalog = connection.getCatalog();
    if (StringUtils.isBlank(catalog)) {
        throw new IllegalArgumentException("databaseName is required");
    }
    operation.setDatabaseName(catalog);
}
routineManager.previewInvocation(connection, operation);
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isBlank(operation.getDatabaseName())) {
    String catalog = connection.getCatalog();
    if (StringUtils.isBlank(catalog)) {
        throw new IllegalArgumentException("databaseName is required");
    }
    operation.setDatabaseName(catalog);
}

Type guard

static boolean hasDatabaseName(RoutineOperation op) {
    return op != null && StringUtils.isNotBlank(op.getDatabaseName());
}

Prevention

When it happens

Trigger: Calling a routine-manager method that triggers buildMigrationPlan or queryRoutineParameters with operation.getDatabaseName() returning null, empty, or whitespace-only.

Common situations: The frontend submits a routine operation without the active database context; the connection's current database was not propagated into the operation; a multi-step wizard lost the database selection between steps.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/bbc24da4dcc6753e. Report an issue: GitHub.

Appendix: source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/MysqlRoutineManager.java:344

        String normalized = StringUtils.trimToEmpty(routineType).toUpperCase(Locale.ROOT);
        if (!FUNCTION.equals(normalized) && !PROCEDURE.equals(normalized)) {
            throw new BusinessException("routine.operation.typeUnsupported");
        }
        return normalized;
    }

    private String requireRoutineName(RoutineOperation operation) {
        String routineName = StringUtils.trimToEmpty(operation.getRoutineName());
        if (StringUtils.isBlank(routineName)) {
            throw new BusinessException("routine.operation.nameRequired");
        }
        return routineName;
    }

    private String requireDatabaseName(RoutineOperation operation) {
        String databaseName = StringUtils.trimToEmpty(operation.getDatabaseName());
        if (StringUtils.isBlank(databaseName)) {
            throw new BusinessException("routine.operation.databaseRequired");
        }
        return databaseName;
    }

    private String ensureSqlEndsWithSemicolon(String sql) {
        String trimmed = StringUtils.trimToEmpty(sql);
        if (StringUtils.isBlank(trimmed)) {
            throw new BusinessException("routine.operation.ddlRequired");
        }
        return trimmed.endsWith(";") ? trimmed : trimmed + ";";
    }

    private String mysqlQualifiedName(String databaseName, String routineName) {
        return Arrays.asList(databaseName, routineName).stream()
                .filter(StringUtils::isNotBlank)
                .map(this::quoteMysqlIdentifier)
                .reduce((left, right) -> left + "." + right)
                .orElseThrow(() -> new BusinessException("routine.operation.nameRequired"));

View on GitHub (pinned to 5ee1e990e7)