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.

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)

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.