louislam/uptime-kuma · error · Error

Multiple values were found, expected only one value

Error message

Multiple values were found, expected only one value

What it means

Thrown by mssqlQuerySingleValue when the query returns more than one row. With conditions enabled the monitor needs exactly one scalar; multiple rows are ambiguous and rejected. Detection happens before column-count validation, so this fires first whenever both conditions are violated.

Source

Thrown at server/monitor-types/mssql.js:109

     * @param {string} connectionString The database connection string
     * @param {string} query The query to validate the database with
     * @returns {Promise<any>} Single value from the first column of the first row
     */
    async mssqlQuerySingleValue(connectionString, query) {
        let pool;
        try {
            pool = new mssql.ConnectionPool(connectionString);
            await pool.connect();
            const result = await pool.request().query(query);

            // Check if we have results
            if (!result.recordset || result.recordset.length === 0) {
                throw new Error("Query returned no results");
            }

            // Check if we have multiple rows
            if (result.recordset.length > 1) {
                throw new Error("Multiple values were found, expected only one value");
            }

            const firstRow = result.recordset[0];
            const columnNames = Object.keys(firstRow);

            // Check if we have multiple columns
            if (columnNames.length > 1) {
                throw new Error("Multiple columns were found, expected only one value");
            }

            // Return the single value from the first (and only) column
            return firstRow[columnNames[0]];
        } catch (err) {
            log.debug("sqlserver", "Error caught in the query execution.", err.message);
            throw err;
        } finally {
            if (pool) {
                await pool.close();

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Add TOP 1 (or TOP (1)) plus a deterministic ORDER BY to pick a single row.
  2. Add or tighten a WHERE clause so at most one row matches.
  3. Replace with an aggregate (MAX/MIN/SUM) that collapses to one scalar.
  4. Confirm conditions are actually needed; if not, disable them to use the row-count path.

Example fix

-- before: SELECT cpu_pct FROM metrics ORDER BY ts DESC;   (many rows)
-- after:  SELECT TOP 1 cpu_pct FROM metrics ORDER BY ts DESC;
Defensive patterns

Strategy: validation

Validate before calling

async function rowCount(connStr, query) {
  const pool = new mssql.ConnectionPool(connStr); await pool.connect();
  const r = await pool.request().query(query); await pool.close(); return r.recordset?.length ?? 0;
}

Type guard

function isSingleRow(r) { return r?.recordset?.length === 1; }

Prevention

When it happens

Trigger: monitor.conditions non-empty, result.recordset.length > 1. Typical of SELECT col FROM table without TOP/LIMIT, missing WHERE, or a join that fans out rows.

Common situations: Used SELECT * / SELECT col FROM large table; forgot TOP 1; conditions enabled on a query originally written to return a row count; join produced a cartesian product.

Related errors


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