OtterMind/Chat2DB · error · BusinessException
mysql.account.listUnavailable
mysql.account.listUnavailable
Error message
mysql.account.listUnavailable
What it means
Thrown by MysqlAccountManager.listAccounts after both attempts to read the mysql.user table fail. The method first tries a query including the account_locked column; on failure it retries without that column; if that also throws SQLException it wraps the cause in BusinessException('mysql.account.listUnavailable'). It signals the connected user cannot enumerate accounts at all.
Source
Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/account/MysqlAccountManager.java:51
DatabaseMetaData metaData = connection.getMetaData();
capability.setProductName(metaData.getDatabaseProductName());
capability.setProductVersion(metaData.getDatabaseProductVersion());
} catch (SQLException e) {
capability.setMessage(e.getMessage());
}
capability.setCurrentUser(querySingleString(connection, SQL_SELECT_CURRENT_USER));
return capability;
}
@Override
public List<AccountInfo> listAccounts(Connection connection) {
try {
return queryAccounts(connection, true);
} catch (SQLException lockedColumnError) {
try {
return queryAccounts(connection, false);
} catch (SQLException e) {
throw new BusinessException(ERROR_KEY_ACCOUNT_LIST_UNAVAILABLE, null, e);
}
}
}
@Override
public List<String> showGrants(Connection connection, String user, String host) {
try {
return queryGrants(connection, user, host);
} catch (SQLException e) {
throw new BusinessException(ERROR_KEY_ACCOUNT_GRANTS_UNAVAILABLE, null, e);
}
}
@Override
public AccountPreview preview(AccountOperationRequest command) {
String sql = MysqlAccountSqlBuilder.buildSql(command);
AccountPreview preview = new AccountPreview();
preview.setActionType(command.getActionType());View on GitHub (pinned to 5ee1e990e7)
Solutions
- Grant the connected user SELECT on mysql.user (or a broader account-read privilege appropriate to the deployment).
- Inspect BusinessException.getCause() for the SQLException's SQL state/error code to pinpoint the denial.
- Verify the datasource is genuine MySQL and the columns match the expected schema.
- If the user must remain restricted, disable the account-listing feature for that connection and degrade gracefully.
Example fix
// before
List<AccountInfo> accounts = accountManager.listAccounts(connection);
// after
List<AccountInfo> accounts;
try {
accounts = accountManager.listAccounts(connection);
} catch (BusinessException e) {
if ("mysql.account.listUnavailable".equals(e.getCode())) {
log.warn("Cannot list accounts: {}", rootMessage(e.getCause()));
accounts = Collections.emptyList();
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the connected user can read mysql.user before enabling account listing.
if (!accountManager.capability(connection).isAccountListReadable()) {
return Collections.emptyList();
} Try / catch
try {
return accountManager.listAccounts(connection);
} catch (BusinessException e) {
if ("mysql.account.listUnavailable".equals(e.getCode())) {
log.warn("account list unavailable: {}", rootMessage(e.getCause()));
return Collections.emptyList();
}
throw e;
} Prevention
- Grant SELECT on mysql.user to the inspecting account.
- Check capability().isAccountListReadable() before calling listAccounts.
- Inspect the wrapped SQLException for the SQL state to diagnose denial.
- Degrade the UI gracefully when listing is unavailable.
When it happens
Trigger: listAccounts(connection) where queryAccounts fails both with and without the locked column: the connected user lacks SELECT on mysql.user, the server is a MySQL fork without the expected columns, the connection was dropped, or a non-MySQL server is mistakenly treated as MySQL.
Common situations: Connecting with a restricted application user that has no access to mysql.user; Aurora/RDS privilege restrictions; a proxy or connection-pool reset mid-query; an older MySQL (5.6) lacking the account_locked column combined with a second unrelated failure.
Related errors
- routine.operation.parameterLoadFailed
- mysql.account.grantsUnavailable
- Existing routine definition is empty
- connection error
- database.delete.systemDatabaseForbidden
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/10c3445e9d48120b.
Report an issue: GitHub.