OtterMind/Chat2DB · error · BusinessException

routine.operation.nameRequired

routine.operation.nameRequired

Error message

routine.operation.nameRequired

What it means

Thrown by requireRoutineName when operation.getRoutineName(), after trim, is blank. The routine name is mandatory for every routine operation (preview, migration, invocation) because it becomes the DROP/CREATE/CALL target. There is no default or fallback name.

Source

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

                    .sorted((left, right) -> Integer.compare(left.ordinalPosition(), right.ordinalPosition()))
                    .toList();
        } catch (Exception e) {
            throw new BusinessException("routine.operation.parameterLoadFailed", new Object[]{e.getMessage()}, e);
        }
    }

    private String normalizeRoutineType(String routineType) {
        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 + ";";

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Populate operation.setRoutineName(name) with a non-blank value before invoking the manager.
  2. Validate at the controller/service boundary that routineName is non-blank and return a 400.
  3. Guard the UI so a routine must be selected before the operation button is enabled.
  4. Log the full operation to find which caller omitted the name.

Example fix

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

// after
if (StringUtils.isBlank(operation.getRoutineName())) {
    throw new IllegalArgumentException("routineName is required");
}
routineManager.previewInvocation(connection, operation);
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isBlank(operation.getRoutineName())) {
    throw new IllegalArgumentException("routineName is required");
}

Type guard

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

Prevention

When it happens

Trigger: Any routine-manager method that calls requireRoutineName (buildMigrationPlan, previewInvocation path) with operation.getRoutineName() returning null, empty, or whitespace-only.

Common situations: The frontend submits a routine operation without selecting a routine; a list/tree node with no name is passed through; the request payload was built programmatically and the name field was omitted.

Related errors


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