OtterMind/Chat2DB · warning · BusinessException

largeCellValue.rowNotFound

largeCellValue.rowNotFound

Error message

largeCellValue.rowNotFound

What it means

Thrown while reading a chunk of a large cell value when the prepared SELECT against the source table returns no rows (resultSet.next() is false). The LargeValueReference points at a row identified by primary key, and that row no longer exists in the database at read time.

Source

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

    private static final int BINARY_TYPE_SAMPLE_SIZE = 64 * 1024;
    private static final String TEXT_PLAIN = "text/plain";
    private static final String TEXT_DOWNLOAD = "text/plain;charset=UTF-8";
    private static final String APPLICATION_JSON = "application/json";
    private static final String IMAGE_WILDCARD = "image/*";

    @Override
    public CellValueChunk readChunk(DbCellValueChunkReadRequest readCellValueChunkRequest) {
        LargeValueReference reference = readCellValueChunkRequest == null ? null : readCellValueChunkRequest.getReference();
        Long offsetParam = readCellValueChunkRequest == null ? null : readCellValueChunkRequest.getOffset();
        Integer limitParam = readCellValueChunkRequest == null ? null : readCellValueChunkRequest.getLimit();
        CellValueFormatEnum format = CellValueFormatEnum.fromRequest(
                readCellValueChunkRequest == null ? null : readCellValueChunkRequest.getFormat());
        long offset = Math.max(0L, offsetParam == null ? 0L : offsetParam);
        int limit = normalizeLimit(limitParam, format);
        try (PreparedStatement statement = prepareStatement(reference);
             ResultSet resultSet = statement.executeQuery()) {
            if (!resultSet.next()) {
                throw new BusinessException("largeCellValue.rowNotFound");
            }
            Object value = resultSet.getObject(1);
            int sqlType = reference.getSqlType() == null ? resultSet.getMetaData().getColumnType(1) : reference.getSqlType();
            String columnType = StringUtils.defaultIfBlank(reference.getColumnType(),
                    resultSet.getMetaData().getColumnTypeName(1));
            LargeValueTypeEnum valueType = LargeValueTypeEnum.resolveForRead(value, columnType, sqlType,
                    reference.getValueType());
            return valueType.isBinaryLike()
                    ? readBinaryChunk(resultSet, value, offset, limit, format, reference, valueType)
                    : readTextChunk(resultSet, value, offset, limit, format, reference, valueType);
        } catch (SQLException | IOException e) {
            throw new BusinessException("largeCellValue.readFailed", new Object[]{e.getMessage()}, e);
        }
    }

    @Override
    public CellValueDownload prepareDownload(LargeValueReference reference, String format) {
        try (PreparedStatement statement = prepareStatement(reference);

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Instruct the user to refresh the result set and reopen the cell to obtain a fresh LargeValueReference.
  2. Verify the reference's primary key column(s) are populated and correct before issuing readChunk.
  3. If rows are volatile, shorten the window between generating the reference and reading chunks, or snapshot the row.
Defensive patterns

Strategy: try-catch

Validate before calling

// Best-effort pre-check that the source row still exists
try (PreparedStatement ps = conn.prepareStatement(
        "SELECT 1 FROM " + table + " WHERE " + pkPredicate)) {
    bindPk(ps, reference.getPrimaryKey());
    try (ResultSet rs = ps.executeQuery()) {
        if (!rs.next()) {
            // tell the user to refresh the result set instead of calling readChunk
        }
    }
}

Try / catch

try {
    cellValueService.readChunk(request);
} catch (BusinessException e) {
    if ("largeCellValue.rowNotFound".equals(e.getCode())) {
        // surface 'row no longer exists; refresh the result set' to the user
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: readChunk() is called with a stale LargeValueReference whose primary key was deleted, the row was modified so the key no longer matches, or the underlying table/data changed between result-set generation and the chunk fetch. Concurrent deletes or a transaction visibility mismatch can also produce an empty result.

Common situations: User opens a large cell, leaves it open, then the row is deleted by another session or by a re-run of a query whose result set is now stale; reference carries a primary key that the dialect cannot round-trip.

Related errors


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