NationalSecurityAgency/ghidra · error · UnsatisfiedParameterException

Could not resolve required parameter for next in: {}. Note:

Error message

Could not resolve required parameter for next in: {}. Note: it may be a circular dependency.

What it means

Thrown by DependentServiceResolver.compile() as an UnsatisfiedParameterException when the topological sort of constructors stalls: in a given round no constructor has all its parameter dependencies satisfied, meaning the remaining set is mutually/circularly dependent. The message explicitly notes it may be a circular dependency and lists the unresolved types.

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/generic/depends/DependentServiceResolver.java:117

			}
			Class<?> fCls = f.getType();
			fieldsByClass.computeIfAbsent(fCls, c -> new HashSet<>()).add(f);
			f.setAccessible(true);
		}
	}

	private void compile() throws UnsatisfiedParameterException, UnsatisfiedFieldsException {
		Set<Class<?>> missing = new HashSet<>(fieldsByClass.keySet());
		missing.removeAll(constructors.keySet());
		if (!missing.isEmpty()) {
			throw new UnsatisfiedFieldsException(missing);
		}
		Set<Class<?>> unordered = new HashSet<>(constructors.keySet());
		while (!unordered.isEmpty()) {
			Set<Class<?>> forRound = new HashSet<>(unordered);
			forRound.removeAll(depsByDependents.keySet());
			if (forRound.isEmpty()) {
				throw new UnsatisfiedParameterException(unordered);
			}
			for (Class<?> ready : forRound) {
				Method m = constructors.get(ready);
				unordered.remove(ready);
				ordered.add(new DependentServiceConstructor<>(ready, m));
				for (Iterator<Set<Class<?>>> iterator =
					depsByDependents.values().iterator(); iterator.hasNext();) {
					Set<Class<?>> deps = iterator.next();
					deps.remove(ready);
					if (deps.isEmpty()) {
						iterator.remove();
					}
				}
			}
		}
		assert ordered.size() == constructors.size();
	}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Break the cycle by removing one direction of the dependency (e.g. use field injection or a setter for one side).
  2. Ensure every parameter type of every @DependentService method is itself produced by some @DependentService method.
  3. Inspect the exception's unresolved set and trace each type's parameters to find the cycle or the missing producer.
  4. If the cycle is inherent, restructure so one service is constructed lazily or via a factory that does not require the other at construction time.

Example fix

// before -- cycle
@DependentService public A buildA(B b) { ... }
@DependentService public B buildB(A a) { ... }

// after -- break by removing parameter from one side
@DependentService public A buildA() { ... }
@DependentService public B buildB(A a) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// build dependency graph and detect cycles before invoking resolver
Map<Class<?>, Set<Class<?>>> deps = collectParameterDeps(cls);
if (hasCycle(deps)) {
  throw new IllegalStateException("Circular dependency among services: " + cycle);
}

Try / catch

try {
  DependentServiceResolver.get(cls);
} catch (UnsatisfiedParameterException e) {
  Msg.error(this, "Unresolvable (circular?) dependencies: " + e.getUnresolved());
}

Prevention

When it happens

Trigger: Service A's factory takes a B, and service B's factory takes an A (direct cycle). Longer cycles (A->B->C->A). A factory parameter type that is never produced by any factory, so the dependency can never be cleared. A self-dependent method that takes its own return type as a parameter.

Common situations: Two services that legitimately reference each other during construction; an unregistered dependency type masquerading as a cycle; refactoring that introduces a new parameter creating an inadvertent cycle.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/44dc4fea52698198. Report an issue: GitHub.