spring-projects / spring-projects/spring-data-mongodb

MongoPersistentEntityIndexResolver - Found cycle for generic types using different type params

Open
#5,213 0 comments 0 reactions 1 assignee View on GitHub

@christophstrobl is already working on this.

Since Jun 16, 2026.

type: bug
Dominant language
Java
Stars
1.7k
Forks
1.1k
PR merge metrics
No merged PRs in 30d

Description

MongoPersistentEntityIndexResolver reports a spurious Found cycle when a generic class (e.g. Selection) appears at multiple levels of a document hierarchy with different type arguments. No actual cycle exists in the document structure.

Example structure:

@Document
public class FruitShop {

    public Selection<FruitBasket> fruitBaskets;

}

public class FruitBasket {
    public Selection<String> fruit;
}

public class Selection<T> {

    public T include;
}

On startup, the index resolver logs:

2026-06-15T17:38:50.119+01:00  INFO 93629 --- [    Test worker] m.c.i.MongoPersistentEntityIndexResolver : Found cycle for field 'include' in type 'Selection' for path 'include -> fruit -> include'

Selection<String>.include is List<String> — a terminal type with no further entity graph to traverse. There is no cycle.

Root cause:

CycleGuard.protect() builds a Path of PersistentProperty<?> elements and detects a cycle when Path.append(breadcrumb) finds the breadcrumb already present in the path:

This uses PersistentProperty.equals(), which is implemented by AbstractPersistentProperty.equals() which in turn delegates to Property. This equals method only takes into account the raw type. So the include fields of type Selection are considered equal regardless of their generics - in the example these are Selection<FruitBasket> and Selection<String>.

Impact:

  1. The false CyclicPropertyReferenceException causes the resolver to stop traversing that branch. Any @Indexed, @CompoundIndex, @TextIndexed, or @WildcardIndexed annotations on fields below the falsely-detected cycle will be ignored.
  2. Additional noise in the logs (especially when you have something more complex than the repro)

Expected behaviour:
The resolver should recognise that Selection and Selection are distinct types, and should only report a cycle when the same resolved parameterized type reappears (indicating genuine recursion, e.g. a tree node with List children).

Suggested fix direction:
The cycle detection needs to incorporate the resolved TypeInformation<?> (which I think may already be available).

Reproduction:
https://github.com/jameskennard/spring-data-mongodb-cycle-found-generics

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.