quarkusio/quarkus · error · RuntimeException

Pokemons should have been deleted

Error message

Pokemons should have been deleted

What it means

RuntimeException thrown by testDeleteViaRemove when em.remove() was expected to delete Pokemons 3, 248 and 242 but a subsequent em.find() still returns a non-null entity. The test validates that explicit remove() deletes rows and evicts the corresponding second-level cache entries (expected Counts(0,0,3,4) misses/evictions).

Source

Thrown at integration-tests/hibernate-orm-cache/src/main/java/io/quarkus/it/hibernate/orm/cache/HibernateOrmCacheTestEndpoint.java:511

    private void testDeleteViaRemove() {
        clearStatistics();

        QuarkusTransaction.requiringNew().run(() -> {
            em.remove(em.find(Pokemon.class, 3));
            em.remove(em.find(Pokemon.class, 248));
            em.remove(em.find(Pokemon.class, 242));
        });

        assertRegionStats(new Counts(0, 3, 0, 4), Pokemon.class.getName());

        clearStatistics();

        QuarkusTransaction.requiringNew().run(() -> {
            if (em.find(Pokemon.class, 3) != null
                    || em.find(Pokemon.class, 248) != null
                    || em.find(Pokemon.class, 242) != null) {
                throw new RuntimeException("Pokemons should have been deleted");
            }
        });

        assertRegionStats(new Counts(0, 0, 3, 4), Pokemon.class.getName());
    }

    private static void listExistingPersons(EntityManager em) {
        CriteriaBuilder cb = em.getCriteriaBuilder();

        CriteriaQuery<Person> cq = cb.createQuery(Person.class);
        Root<Person> from = cq.from(Person.class);
        cq.select(from).orderBy(cb.asc(from.get("name")));
        TypedQuery<Person> q = em.createQuery(cq);
        q.setHint("org.hibernate.cacheable", Boolean.TRUE);
        List<Person> allpersons = q.getResultList();
        if (allpersons.size() != 4) {
            throw new RuntimeException("Incorrect number of results");
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure each Pokemon is merged/managed within the same transaction before em.remove() and that the transaction commits
  2. Verify the second-level cache eviction occurs on remove (check assertRegionStats counts for the Pokemon region)
  3. Confirm entity IDs 3, 248, 242 are the ones actually removed (not other IDs)
  4. Reset the DB and cache statistics between test phases (clearStatistics is already called - verify it clears all regions)

Example fix

// before
em.remove(em.find(Pokemon.class, 3));
// after
Pokemon p = em.find(Pokemon.class, 3);
if (p != null) { em.remove(p); em.flush(); }
Defensive patterns

Strategy: validation

Validate before calling

boolean stillThere = em.find(Pokemon.class, 3) != null
    || em.find(Pokemon.class, 248) != null
    || em.find(Pokemon.class, 242) != null;
if (stillThere) throw new IllegalStateException("Remove phase did not delete all target pokemons");

Try / catch

try {
    testDeleteViaRemove();
} catch (RuntimeException e) {
    if (e.getMessage().equals("Pokemons should have been deleted")) {
        // check remove() ran on managed entities and transaction committed
    }
}

Prevention

When it happens

Trigger: em.find(Pokemon.class, 3/248/242) returns non-null inside the verification transaction after the remove phase, so the code throws 'Pokemons should have been deleted'. Typically the remove was rolled back, ran on detached instances, or a cached entity is served from a region that was not evicted.

Common situations: remove() called on a detached entity without the entity being managed in the same transaction; remove transaction not committed; second-level cache region for Pokemon retaining entities after delete; test ordering issues leaving stale rows from earlier phases.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/c3b07283f31e8797. Report an issue: GitHub.