OtterMind/Chat2DB · error · BusinessException

jdbc.driver.downloadFailed

jdbc.driver.downloadFailed

Error message

jdbc.driver.downloadFailed

What it means

Thrown by DbJdbcDriverServiceImpl.downloadBuiltinDriversOrThrow to wrap an IOException from downloadBuiltinDrivers (which loops driverConfig download URLs and calls JdbcJarUtils.download). The underlying cause is a network/IO failure fetching the JDBC driver jar. The code 'jdbc.driver.downloadFailed' is NOT a defined i18n key, so the user-facing message becomes the raw 'jdbc.driver.downloadFailed : no message.' with e.getMessage() effectively lost from the resolved text (the arg is passed but there is no message template to interpolate).

Solutions

  1. Verify the host can reach each URL in driverConfig.getDownloadJdbcDriverUrls() (curl the first URL).
  2. Configure the network proxy / allow-list for the driver download host.
  3. Pre-place the driver jar in JdbcDriverConstants.DRIVER_LIB_PATH so no download is needed.
  4. Add the i18n key 'jdbc.driver.downloadFailed=Failed to download JDBC driver: {0}' so the IOException message is surfaced.

Example fix

// before
throw new BusinessException("jdbc.driver.downloadFailed", new Object[]{e.getMessage()}, e);
// renders: "jdbc.driver.downloadFailed : no message."

// after (add to messages_en_US.properties)
// jdbc.driver.downloadFailed=Failed to download JDBC driver: {0}
// renders: "Failed to download JDBC driver: <io message>"
Defensive patterns

Strategy: retry

Validate before calling

for (String url : driverConfig.getDownloadJdbcDriverUrls()) {
    try { JdbcJarUtils.download(url); break; }
    catch (IOException ignore) { /* try next mirror */ }
}

Try / catch

try {
    driverService.downloadBuiltinDriversOrThrow(dbType);
} catch (BusinessException e) { // code jdbc.driver.downloadFailed
    // surface e.getCause().getMessage(); prompt proxy/offline driver placement
}

Prevention

When it happens

Trigger: Connecting to a datasource whose driver jar must be downloaded (not bundled) and the download URL is unreachable (404, DNS, proxy, timeout, TLS, auth). Triggered at connection-establishment time when drivers are fetched on demand.

Common situations: Offline/air-gapped host with no internet egress; a driver download host that moved or requires a proxy; a corporate firewall blocking the jar URL; a stale driverConfig pointing at an old maven/CDN path.

Related errors


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

Appendix: source

Thrown at chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbJdbcDriverServiceImpl.java:126

    @Override
    public void downloadBuiltinDrivers(String dbType) throws IOException {
        DBConfig dbConfig = queryDbConfig(dbType);
        List<DriverConfig> driverConfigList = dbConfig.getDriverConfigList();
        for (DriverConfig driverConfig : driverConfigList) {
            List<String> downloadJdbcDriverUrls = driverConfig.getDownloadJdbcDriverUrls();
            for (String downloadJdbcDriverUrl : downloadJdbcDriverUrls) {
                JdbcJarUtils.download(downloadJdbcDriverUrl);
            }
        }
    }

    @Override
    public void downloadBuiltinDriversOrThrow(String dbType) {
        try {
            downloadBuiltinDrivers(dbType);
        } catch (IOException e) {
            throw new BusinessException("jdbc.driver.downloadFailed", new Object[]{e.getMessage()}, e);
        }
    }

    @Override
    public void downloadStartupDrivers() {
        List<String> urls = new ArrayList<>();
        Chat2DBContext.PLUGIN_MAP.forEach((k, v) -> {
            try {
                DBConfig dbConfig = v.getDBConfig();
                if (dbConfig != null) {
                    dbConfig.getDriverConfigList().forEach(driverConfig -> {
                        if (driverConfig != null && driverConfig.getDownloadJdbcDriverUrls() != null
                                && !driverConfig.getDownloadJdbcDriverUrls().isEmpty()
                                && "MYSQL".equals(driverConfig.getDbType())) {
                            urls.addAll(driverConfig.getDownloadJdbcDriverUrls());
                        }
                    });
                }

View on GitHub (pinned to 5ee1e990e7)