skylot/jadx · error · JadxRuntimeException
Init of enum field '{}' uses external variables
Error message
Init of enum field '{}' uses external variables What it means
Thrown by EnumVisitor when processing an enum constant's constructor call and finding that the constructor arguments reference register variables that cannot be inlined (inlineExternalRegs returns null). Enum constant initialisation should use only constant/literal values; references to external registers indicate the enum's $VALUES or <clinit> uses computed values that jadx cannot statically resolve.
Source
Thrown at jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java:485
return null;
}
// usually constructor signature is '<init>(Ljava/lang/String;I)V'
// sometimes one or both args can be inlined or omitted
String nameStr = null;
if (co.getArgsCount() == 0) {
ConstructorInsn ctrInsn = searchEnumSuperCtrInsn(ctrMth);
if (ctrInsn != null && ctrInsn.getArgsCount() != 0) {
nameStr = getConstString(ctrMth.root(), ctrInsn.getArg(0));
}
} else {
nameStr = getConstString(cls.root(), co.getArg(0));
// verify and try to inline additional constructor args
List<RegisterArg> regs = new ArrayList<>();
co.getRegisterArgs(regs);
if (!regs.isEmpty()) {
ConstructorInsn replacedCo = inlineExternalRegs(data, co);
if (replacedCo == null) {
throw new JadxRuntimeException("Init of enum field '" + enumFieldNode.getName() + "' uses external variables");
}
data.toRemove.add(co);
co = replacedCo;
}
}
return new EnumField(enumFieldNode, co, nameStr);
}
private @Nullable ConstructorInsn searchEnumSuperCtrInsn(MethodNode ctrMth) {
for (BlockNode block : ctrMth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) {
if (insn.getType() == InsnType.CONSTRUCTOR) {
ConstructorInsn ctrCall = (ConstructorInsn) insn;
if (ctrCall.isSuper()
&& ctrCall.getArgsCount() != 0
&& ctrCall.getCallMth().getRawFullId().equals(ENUM_SUPER_CONSTRUCTOR_ID)) {
return ctrCall;
}View on GitHub (pinned to e738a26571)
Solutions
- Upgrade jadx — enum-handling heuristics improve with each release.
- Catch JadxRuntimeException per class and skip the enum, allowing other classes to decompile.
- Report the issue with the enum class name and field name from the error message.
- Try alternative decompiler settings or tools for the specific class.
Defensive patterns
Strategy: try-catch
Try / catch
try {
javaClass.decompile();
} catch (JadxRuntimeException e) {
LOG.warn("Enum init with external vars in {}: {}", javaClass.getName(), e.getMessage());
} Prevention
- Upgrade jadx for improved enum-handling heuristics.
- Catch per class to continue the batch.
- Report obfuscated enum patterns that trigger the failure.
- Use alternative decompiler settings or tools for the specific enum class.
When it happens
Trigger: During enum class processing, a ConstructorInsn (co) for an enum field has register args (co.getRegisterArgs(regs) is non-empty). inlineExternalRegs(data, co) is called to resolve them but returns null — the registers reference values from outside the static initialiser that cannot be folded into constants.
Common situations: Enums in obfuscated code where the compiler or obfuscator generates complex <clinit> logic with shared registers. Also seen when an enum's constructor arguments are computed at runtime rather than being literals. Standard enum patterns (enum E { A, B }) work fine.
Related errors
- Bad name for type variable: {}
- Can't parse type: {}, unexpected: {}
- No inner type found: {}
- Unexpected inner type found: {}
- Failed to parse generic types map
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/09548397b2dc1f0e.
Report an issue: GitHub.