{"record":{"id":"b54527c247fdf47c","repo":"greenrobot/greenDAO","slug":"expected-unique-result-but-count-was-cursor-get","errorCode":null,"errorMessage":"Expected unique result, but count was ${cursor.getCount()}","messagePattern":"Expected unique result, but count was (.+?)","errorType":"exception","errorClass":"DaoException","httpStatus":null,"severity":"error","filePath":"DaoCore/src/main/java/org/greenrobot/greendao/AbstractDao.java","lineNumber":170,"sourceCode":"        String[] idArray = new String[]{Long.toString(rowId)};\n        Cursor cursor = db.rawQuery(statements.getSelectByRowId(), idArray);\n        return loadUniqueAndCloseCursor(cursor);\n    }\n\n    protected T loadUniqueAndCloseCursor(Cursor cursor) {\n        try {\n            return loadUnique(cursor);\n        } finally {\n            cursor.close();\n        }\n    }\n\n    protected T loadUnique(Cursor cursor) {\n        boolean available = cursor.moveToFirst();\n        if (!available) {\n            return null;\n        } else if (!cursor.isLast()) {\n            throw new DaoException(\"Expected unique result, but count was \" + cursor.getCount());\n        }\n        return loadCurrent(cursor, 0, true);\n    }\n\n    /** Loads all available entities from the database. */\n    public List<T> loadAll() {\n        Cursor cursor = db.rawQuery(statements.getSelectAll(), null);\n        return loadAllAndCloseCursor(cursor);\n    }\n\n    /** Detaches an entity from the identity scope (session). Subsequent query results won't return this object. */\n    public boolean detach(T entity) {\n        if (identityScope != null) {\n            K key = getKeyVerified(entity);\n            return identityScope.detach(key, entity);\n        } else {\n            return false;\n        }","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/greenrobot/greenDAO/blob/0bbb338e17c4cf28aba5aae62d42f73f50186157/DaoCore/src/main/java/org/greenrobot/greendao/AbstractDao.java#L152-L188","documentation":"greenDAO's loadUnique(Cursor) expects a query that returns at most one row. If the cursor is positioned on the first row but isLast() is false, more than one row matched, so it throws DaoException. This protects API contracts where the caller assumes a unique result.","triggerScenarios":"Calling loadUnique()/loadUniqueAndCloseCursor() on a query whose WHERE clause matches more than one row — typically a query on a non-unique column or a queryBuilder whereUnique/where condition that isn't actually unique.","commonSituations":"Querying by a column assumed unique but not declared UNIQUE in the schema; duplicated rows after a schema migration or manual inserts; using loadUnique where load() by primary key or a list query was intended.","solutions":["Make the query condition actually unique (query by primary key or a column with a UNIQUE index).","Use query().list()/listIterator() instead of loadUnique if multiple rows are legitimate.","Deduplicate existing data with DELETE/UPDATE so at most one row matches the condition.","Add a UNIQUE constraint to the column so duplicates cannot be inserted (with schema migration)."],"exampleFix":"// before\nUser u = userDao.queryBuilder().where(UserDao.Properties.Email.eq(email)).unique();\n// after (column not guaranteed unique — handle list)\nList<User> users = userDao.queryBuilder().where(UserDao.Properties.Email.eq(email)).list();\nUser u = users.isEmpty() ? null : users.get(0);","handlingStrategy":"validation","validationCode":"long count = userDao.queryBuilder().where(Properties.Email.eq(email)).buildCount().count();\nif (count > 1) throw new IllegalStateException(\"Duplicate rows for email: \" + email);","typeGuard":null,"tryCatchPattern":"try {\n    User u = userDao.queryBuilder().where(Properties.Email.eq(email)).unique();\n    // use u (may be null)\n} catch (DaoException e) {\n    // multiple rows matched: fall back to list query and pick/dedupe\n    List<User> all = userDao.queryBuilder().where(Properties.Email.eq(email)).list();\n}","preventionTips":["Add UNIQUE constraints to columns used with .unique()/loadUnique.","Prefer load(pk) for primary-key lookups.","Deduplicate data after migrations.","Use list() when uniqueness is not schema-guaranteed."],"tags":["database","greendao","query","duplicate-rows"],"backgroundTag":"unexpected-response-shape","analyzedSha":"0bbb338e17c4cf28aba5aae62d42f73f50186157","analyzedAt":"2026-09-08T03:22:36.050Z","contentChangedAt":"2026-09-08T03:22:36.050Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}