louislam/uptime-kuma · error · Error

Multiple columns were found, expected only one value

Error message

Multiple columns were found, expected only one value

What it means

The OracleDB monitor expects a SQL query that returns exactly one scalar value (one row, one column). After verifying rows.length === 1, it inspects the first row's keys; if Object.keys(firstRow).length > 1, the SELECT projected more than one column and there is no unambiguous value to report, so it aborts rather than guessing. This is a usage contract enforced by the monitor, not by the oracledb driver itself.

Source

Thrown at server/monitor-types/oracledb.js:138

                password: password,
            });
            const result = await connection.execute(query, [], {
                outFormat: oracledb.OUT_FORMAT_OBJECT,
            });

            if (!result.rows || result.rows.length === 0) {
                throw new Error("Query returned no results");
            }

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

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

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

            return firstRow[columnNames[0]];
        } catch (error) {
            log.debug(this.name, "Error caught in the query execution.", error.message);
            throw error;
        } finally {
            if (connection) {
                await connection.close();
            }
        }
    }
}

module.exports = {
    OracleDbMonitorType,
};

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Rewrite the monitor query to project exactly one column, e.g. SELECT count(*) FROM table.
  2. Wrap multi-column logic in a scalar subquery, e.g. SELECT (SELECT count(*) FROM t) FROM dual.
  3. Validate the query in SQL*Plus / SQL Developer first and confirm a single value cell is returned.
  4. If you need multiple metrics, create one OracleDB monitor per metric rather than one multi-column query.

Example fix

// before
const sql = "SELECT id, name FROM users WHERE rownum = 1";
// after
const sql = "SELECT count(*) FROM users";
Defensive patterns

Strategy: validation

Validate before calling

// Before running the OracleDB monitor, sanity-check the query shape by
// executing it once with ROWNUM = 1 and asserting a single column.
async function validateOracleScalarQuery(pool, sql) {
  const wrapped = `SELECT * FROM (${sql}) WHERE ROWNUM = 1`;
  const r = await pool.execute(wrapped);
  const row = r.rows && r.rows[0];
  if (!row) throw new Error('Query returned no rows');
  const cols = Object.keys(row);
  if (cols.length !== 1) {
    throw new Error(`Query must return exactly 1 column, got ${cols.length}: ${cols.join(', ')}`);
  }
}

Type guard

// Narrow a query result to a single scalar.
function isScalarRow(row) {
  return !!row && typeof row === 'object' && Object.keys(row).length === 1;
}

Try / catch

// In a wrapper around the monitor query: distinguish multi-column from multi-row.
try {
  await oracledbMonitor.check(monitor, heartbeat, server);
} catch (e) {
  if (/Multiple columns were found/.test(e.message)) {
    log.error('Fix the monitor query to SELECT a single column');
  }
  throw e;
}

Prevention

When it happens

Trigger: A monitor's query string returns multiple columns, e.g. SELECT id, name FROM users or SELECT count(*), max(ts) FROM logs. Any query whose first row deserializes to an object with two or more own keys trips the guard at oracledb.js:138 before the return.

Common situations: Authoring a diagnostic query with extra columns for context, copy-pasting a row-returning query into a single-value monitor, or a query that conditionally adds columns. The earlier rows.length > 1 check ('Multiple values were found') handles multi-row cases; this one is specifically multi-column.

Related errors


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