louislam/uptime-kuma · error · Error

Database connection/query failed: ${error.message}

Error message

Database connection/query failed: ${error.message}

What it means

Catch-all wrapper in MysqlMonitorType.check: any error whose message does NOT contain 'did not meet the specified conditions' is re-thrown as 'Database connection/query failed: <original>'. This wraps connection, auth, TLS, timeout, and SQL syntax errors from the mysql driver callback/promise chain.

Source

Thrown at server/monitor-types/mysql.js:60

                    throw new Error(`Query result did not meet the specified conditions (${result})`);
                }

                heartbeat.status = UP;
                heartbeat.msg = "Query did meet specified conditions";
            } else {
                // Backwards compatible: just check connection and return row count
                const result = await this.mysqlQuery(monitor.databaseConnectionString, query, password);
                heartbeat.ping = dayjs().valueOf() - startTime;
                heartbeat.status = UP;
                heartbeat.msg = result;
            }
        } catch (error) {
            heartbeat.ping = dayjs().valueOf() - startTime;
            // Re-throw condition errors as-is, wrap database errors
            if (error.message.includes("did not meet the specified conditions")) {
                throw error;
            }
            throw new Error(`Database connection/query failed: ${error.message}`);
        }
    }

    /**
     * Run a query on MySQL/MariaDB (backwards compatible - returns row count)
     * @param {string} connectionString The database connection string
     * @param {string} query The query to execute
     * @param {string} password Optional password override
     * @returns {Promise<string>} Row count message
     */
    mysqlQuery(connectionString, query, password = undefined) {
        return new Promise((resolve, reject) => {
            const connection = mysql.createConnection({
                uri: connectionString,
                password,
            });

            connection.on("error", (err) => {

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Connect with the mysql CLI from the Uptime Kuma host using the same DSN/credentials.
  2. Verify the user is allowed from the monitor's IP (SELECT user, host FROM mysql.user) and that auth plugin is supported.
  3. If TLS is required, add ssl options to the connection string / DSN.
  4. Run the query standalone to surface parse/permission errors.
  5. Confirm server max_connections / wait_timeout is not exhausting the monitor.

Example fix

// before: mysql://u:p@10.0.0.5:3306/app   (caching_sha2_password needs TLS)
// after:  mysql://u:p@10.0.0.5:3306/app?ssl={'rejectUnauthorized':true}
Defensive patterns

Strategy: retry

Validate before calling

function canConnect(dsn, ms=2000) {
  const m = dsn.match(/mysql:\/\/([^:@\/]+)(?::[^@]*)?@([^:\/]+):(\d+)/);
  const [, , host, port] = m ? m : [,,'',3306]; return portOpen(host, Number(port||3306), ms);
}

Try / catch

async function withRetry(fn, retries=3, base=1000) {
  for (let i=0;i<=retries;i++){ try { return await fn(); } catch(e){
    if (/Database connection\/query failed/.test(e.message) && i<retries) await sleep(base*2**i); else throw e; } }
}

Prevention

When it happens

Trigger: mysqlQuery/mysqlQuerySingleValue rejects: ECONNREFUSED, ETIMEDOUT, ER_ACCESS_DENIED_ERROR, ER_PARSE_ERROR, PROTOCOL_CONNECTION_LOST, SSL handshake failures, or the single-value validation errors. The substring guard re-throws condition-mismatch messages unchanged and wraps everything else.

Common situations: Wrong host/port (default 3306); bind-address only on localhost; user host wildcard missing ('user'@'%'); caching_sha2_password auth requiring TLS; wrong database name; SQL syntax error; connection pool limits hit on the server.

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/3cf7e64877570a8d. Report an issue: GitHub.