apache/cassandra · error · RuntimeException

Invalid row " + row + " in table: " +…

Error message

Invalid row " + row + " in table: " + latenciesMetricsTableName

What it means

getLatenciesMetricsFromVtable reads percentile latency rows from the CIDRFilteringMetrics latencies virtual table. Every row must contain the metric name and the P50 column (percentile family P95/P99/P999/P999_MAX is read afterwards); a row missing NAME_COL or P50_COL cannot be parsed, so a RuntimeException flags it.

Solutions

  1. Ensure all nodes are on the same Cassandra version so the latencies virtual table emits all percentile columns.
  2. Confirm the SELECT statement projects the full column set (name + p50/p95/p99/p999/p999_max).
  3. Re-execute the query against a specific healthy node.
  4. Treat persistent occurrences as an internal bug and report with the offending row's column list.
Defensive patterns

Strategy: try-catch

Validate before calling

for (UntypedResultSet.Row row : result)
    if (!row.has("name") || !row.has("p50"))
        throw new IllegalStateException("CIDR latencies table schema mismatch; check node versions");

Try / catch

try {
    latencies = getLatenciesMetricsFromVtable();
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Invalid row")) {
        logger.warn("CIDR latency metrics unavailable: {}", e.getMessage());
        latencies = Collections.emptyMap(); // fallback
    } else throw e;
}

Prevention

When it happens

Trigger: The prepared getLatenciesMetricsStatement returns rows lacking the name or P50 columns — typically because the latencies virtual table schema on some node differs (version skew, partially applied change) or the SELECT was altered to fetch fewer columns.

Common situations: Mixed-version clusters during rolling upgrade where percentile column set changed; customized monitoring scripts replacing the built-in statement; reading the table from a node whose virtual-table implementation is older.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/7520118139077cb5. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/virtual/CIDRFilteringMetricsTable.java:244

    }

    public Map<String, List<Double>> getLatenciesMetricsFromVtable()
    {
        String latenciesMetricsTableName = SchemaConstants.VIRTUAL_VIEWS + '.' +
                                           CIDRFilteringMetricsTable.CIDRFilteringMetricsLatenciesTable.TABLE_NAME;

        SelectStatement getLatenciesMetricsStatement =
            (SelectStatement) QueryProcessor.getStatement(String.format("SELECT * FROM %s", latenciesMetricsTableName),
                                                          ClientState.forInternalCalls());

        Map<String, List<Double>> metrics = new HashMap<>();

        UntypedResultSet result = retrieveRows(getLatenciesMetricsStatement);
        for (UntypedResultSet.Row row : result)
        {
            if (!row.has(CIDRFilteringMetricsLatenciesTable.NAME_COL) ||
                !row.has(CIDRFilteringMetricsLatenciesTable.P50_COL))
                throw new RuntimeException("Invalid row " + row + " in table: " + latenciesMetricsTableName);

            metrics.put(row.getString(CIDRFilteringMetricsTable.CIDRFilteringMetricsLatenciesTable.NAME_COL),
                        Arrays.asList(row.getDouble(CIDRFilteringMetricsLatenciesTable.P50_COL),
                                      row.getDouble(CIDRFilteringMetricsLatenciesTable.P95_COL),
                                      row.getDouble(CIDRFilteringMetricsLatenciesTable.P99_COL),
                                      row.getDouble(CIDRFilteringMetricsLatenciesTable.P999_COL),
                                      row.getDouble(CIDRFilteringMetricsLatenciesTable.MAX_COL)));
        }

        return metrics;
    }
}

View on GitHub (pinned to 88fd0f6a0e)