greenrobot/greenDAO · error · DaoException

Cannot update entity without key - was it inserted before?

Error message

Cannot update entity without key - was it inserted before?

What it means

update() executes a prepared UPDATE statement that binds the entity's primary key in the WHERE clause. If getKey(entity) returns null, there is no key to bind and greenDAO throws DaoException — the entity was likely never inserted, so it cannot be updated.

Solutions

  1. Call insert(entity) first so the DB assigns a key, then update.
  2. Use insertOrUpdate(entity) to handle both cases.
  3. Check getKey(entity) != null before updating.
  4. Generate/assign the primary key manually before update if the schema allows it.

Example fix

// before
User u = new User("alice");
userDao.update(u); // throws: no key
// after
User u = new User("alice");
userDao.insert(u); // assigns key
u.setName("alice2");
userDao.update(u);
Defensive patterns

Strategy: validation

Validate before calling

if (userDao.getKey(entity) == null) {
    userDao.insert(entity);
} else {
    userDao.update(entity);
}

Type guard

boolean isPersisted(T e) { return dao.getKey(e) != null; }

Try / catch

try {
    userDao.update(entity);
} catch (DaoException e) {
    if (e.getMessage().contains("without key")) {
        userDao.insertOrUpdate(entity);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling update(entity) or updateInsideSynchronized with an entity whose primary key field is null — typically a freshly constructed object never inserted via insert().

Common situations: Creating a new entity and calling update instead of insert; an entity deserialized/copied without its id; resetting the id field to null before update; using updateInTx with un-persisted objects.

Related errors


AI-assisted analysis of greenrobot/greenDAO@0bbb338e17 (2026-09-08). Data as JSON: /api/errors/de45e090ad3a14a5. Report an issue: GitHub.

Appendix: source

Thrown at DaoCore/src/main/java/org/greenrobot/greendao/AbstractDao.java:804

            } finally {
                db.endTransaction();
            }
        }
    }

    public QueryBuilder<T> queryBuilder() {
        return QueryBuilder.internalCreate(this);
    }

    protected void updateInsideSynchronized(T entity, DatabaseStatement stmt, boolean lock) {
        // To do? Check if it's worth not to bind PKs here (performance).
        bindValues(stmt, entity);
        int index = config.allColumns.length + 1;
        K key = getKey(entity);
        if (key instanceof Long) {
            stmt.bindLong(index, (Long) key);
        } else if (key == null) {
            throw new DaoException("Cannot update entity without key - was it inserted before?");
        } else {
            stmt.bindString(index, key.toString());
        }
        stmt.execute();
        attachEntity(key, entity, lock);
    }

    protected void updateInsideSynchronized(T entity, SQLiteStatement stmt, boolean lock) {
        // To do? Check if it's worth not to bind PKs here (performance).
        bindValues(stmt, entity);
        int index = config.allColumns.length + 1;
        K key = getKey(entity);
        if (key instanceof Long) {
            stmt.bindLong(index, (Long) key);
        } else if (key == null) {
            throw new DaoException("Cannot update entity without key - was it inserted before?");
        } else {
            stmt.bindString(index, key.toString());

View on GitHub (pinned to 0bbb338e17)