skylot/jadx · error · UnsupportedOperationException

Centrality state is not supported for {}

Error message

Centrality state is not supported for {}

What it means

Thrown as UnsupportedOperationException by TraverserState.getCentralityState() when getUnderlyingCentralityState() returns null. CentralityState tracks whether a traverser state allows central (merged) output and which output registers are permitted. Not all state types carry centrality — terminal states, global source states, and some cache-recovery states intentionally return null. Calling getCentralityState() on such a state is a programming error: the caller must check via the underlying accessor or ensure the state type supports centrality before calling.

Source

Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/finaly/traverser/state/TraverserState.java:97

		sb.append(secondIndent);
		TraverserBlockInfo blockInsnInfo = getBlockInsnInfo();
		if (blockInsnInfo != null) {
			sb.append(blockInsnInfo.toString(secondIndent));
		} else {
			sb.append("NO ACTIVE BLOCK");
		}
		sb.append(System.lineSeparator());

		sb.append(baseIndent);
		sb.append("}");
		return sb.toString();
	}

	public final CentralityState getCentralityState() {
		CentralityState underlying = getUnderlyingCentralityState();
		if (underlying == null) {
			throw new UnsupportedOperationException("Centrality state is not supported for " + getClass().getName());
		}
		return underlying;
	}

	public final @Nullable TraverserBlockInfo getBlockInsnInfo() {
		return getUnderlyingBlockInsnInfo();
	}

	public final GlobalTraverserSourceState getGlobalState() {
		return getComparatorState().getGlobalStateFor(this);
	}
}

View on GitHub (pinned to e738a26571)

Solutions

  1. Report to jadx developers with the input and stack trace.
  2. Workaround: disable the finally extraction pass.
  3. If developing jadx, call getUnderlyingCentralityState() (or the public getBlockInsnInfo()) first and skip centrality-dependent logic when null.

Example fix

// before
CentralityState cs = state.getCentralityState();
boolean allowsCentral = cs.getAllowsCentral();

// after
CentralityState cs = state.getUnderlyingCentralityState();
if (cs == null) {
    return; // this state type does not support centrality
}
boolean allowsCentral = cs.getAllowsCentral();
Defensive patterns

Strategy: type-guard

Type guard

// Check for null centrality before calling getCentralityState()
CentralityState cs = state.getUnderlyingCentralityState();
if (cs == null) {
    // This state type does not support centrality
    return;
}
// Safe to use cs
boolean allowsCentral = cs.getAllowsCentral();

Prevention

When it happens

Trigger: A visitor or handler calls state.getCentralityState() on a state subclass whose getUnderlyingCentralityState() returns null. This happens when code assumes all states have centrality but encounters a terminal or transitional state. Note that TraverserState.toString() safely checks for null before calling getCentralityState(), so only direct external callers are affected.

Common situations: New visitor or handler code added to the finally traverser that does not guard for null centrality. Typically surfaces during testing on edge-case inputs that produce terminal states early in traversal.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/bb6b2df72b15fbb1. Report an issue: GitHub.