{"record":{"id":"2711351c296186aa","repo":"OtterMind/Chat2DB","slug":"largecellvalue-rowlocatorrequired","errorCode":"largeCellValue.rowLocatorRequired","errorMessage":"largeCellValue.rowLocatorRequired","messagePattern":"largeCellValue\\.rowLocatorRequired","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbCellValueServiceImpl.java","lineNumber":124,"sourceCode":"            throw new BusinessException(\"largeCellValue.downloadFailed\", new Object[]{e.getMessage()}, e);\n        }\n    }\n\n    private int normalizeLimit(Integer limit, CellValueFormatEnum format) {\n        int resolved = limit == null || limit <= 0 ? DEFAULT_CHUNK_SIZE : limit;\n        resolved = Math.min(resolved, MAX_CHUNK_SIZE);\n        if (format.isBase64() && resolved < BASE64_BYTE_GROUP) {\n            return BASE64_BYTE_GROUP;\n        }\n        if (format.isBase64() && resolved > BASE64_BYTE_GROUP) {\n            return resolved - (resolved % BASE64_BYTE_GROUP);\n        }\n        return resolved;\n    }\n\n    private PreparedStatement prepareStatement(LargeValueReference reference) throws SQLException {\n        if (reference.getPrimaryKey() == null || reference.getPrimaryKey().isEmpty()) {\n            throw new BusinessException(\"largeCellValue.rowLocatorRequired\");\n        }\n        Connection connection = Chat2DBContext.getConnection();\n        IDbMetaData metaData = Chat2DBContext.getDbMetaData();\n        QualifiedTableName tableName = parseQualifiedTableName(reference);\n        StringBuilder sql = new StringBuilder();\n        sql.append(\"SELECT \")\n                .append(metaData.getMetaDataName(reference.getColumnName()))\n                .append(\" FROM \")\n                .append(metaData.getQualifiedTableName(tableName.databaseName(), tableName.schemaName(),\n                        tableName.tableName()))\n                .append(\" WHERE \");\n        boolean first = true;\n        for (String columnName : reference.getPrimaryKey().keySet()) {\n            if (!first) {\n                sql.append(\" AND \");\n            }\n            sql.append(metaData.getMetaDataName(columnName)).append(\" = ?\");\n            first = false;","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbCellValueServiceImpl.java#L106-L142","documentation":"Thrown by prepareStatement() when the LargeValueReference has a null or empty primary key. The large-value lookup builds 'SELECT col FROM table WHERE pk = ?' and cannot locate a row without primary-key coordinates.","triggerScenarios":"readChunk() or prepareDownload() is called with a reference whose getPrimaryKey() is null/empty — typically because the source result row was not uniquely identifiable (no primary key on the table, or a custom query without a row locator).","commonSituations":"Querying a table or view that has no primary key / no unique index, so the reference could not capture row locator info; or the reference was built from a result set that doesn't expose editable row identity.","solutions":["Ensure the source table has a primary key or unique identifier so a row locator can be captured.","For non-editable result sets without identity, inform the user that large-cell read/download is unavailable (see largeCellValue.fullValueUnsupported).","Validate the reference carries a non-empty primary key before calling readChunk/prepareDownload."],"exampleFix":"// before\n// reference with null primaryKey reaches prepareStatement()\n// after (caller guard)\nif (reference.getPrimaryKey() == null || reference.getPrimaryKey().isEmpty()) {\n    throw new BusinessException(\"largeCellValue.rowLocatorRequired\");\n}","handlingStrategy":"validation","validationCode":"// Guard before readChunk/prepareDownload\nList<Object> pk = reference.getPrimaryKey();\nif (pk == null || pk.isEmpty()) {\n    // large-cell read/download is unavailable; tell the user the row must be uniquely identifiable\n    return Result.fail(\"largeCellValue.rowLocatorRequired\");\n}","typeGuard":"// Java guard narrowing on reference identity\nboolean hasRowLocator(LargeValueReference ref) {\n    return ref != null && ref.getPrimaryKey() != null && !ref.getPrimaryKey().isEmpty();\n}","tryCatchPattern":null,"preventionTips":["Only offer large-cell read/download for tables with a primary key or unique locator.","Capture row locator info when building references; reject references without it early.","Surface 'full value unavailable' for non-identifiable result rows instead of attempting lookup."],"tags":["cell-value","large-value","validation","primary-key"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}