pxb1988/dex2jar · error · RuntimeException

invalid ret type:

Error message

invalid ret type:

What it means

Thrown by InvocationWeaver.unBox after generating the callback invocation: after the mapped method's return value is handled (void results are POP/POP2-ed), the new (mapped) return type must be an OBJECT sort so unboxing/conversion logic can proceed. A primitive or ARRAY new return type indicates the weaver cannot convert the replacement method's return value to the original method's return type.

Solutions

  1. Fix the mapping configuration so the replacement method's return type is an object type compatible with the original return type.
  2. If a primitive result is needed, wrap it: return java/lang/Integer and let the original descriptor's unboxing path convert it.
  3. If the original return should be ignored, change the mapping so the original return type is void rather than making the new return primitive.
  4. Check the descriptor of mapTo in the config for typos (e.g. ')I' vs ')Ljava/lang/Integer;').

Example fix

// before (mapping config)
ret = I
// after
ret = Ljava/lang/Integer;
Defensive patterns

Strategy: validation

Validate before calling

// validate the mapping before weaving
Type nRet = Type.getReturnType(mapTo.desc);
if (nRet.getSort() != Type.OBJECT && nRet.getSort() != Type.VOID) {
    throw new IllegalArgumentException("mapTo must return an object type, got: " + nRet);
}

Try / catch

try {
    new InvocationWeaver(cfg).weave();
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("invalid ret type")) {
        throw new IllegalStateException("Fix the mapping: replacement method must return an object type", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring a method mapping whose replacement (mapTo) returns a primitive type (e.g. I, J, Z) or array sort instead of an object type, then running the weaver via genMethodACode or newMethodCallback while the original method's return is non-void.

Common situations: Writing a transform config that replaces a method returning java.lang.Integer/object with one returning int, or mapping a method whose return type was authored with the wrong descriptor in the weaving configuration.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08). Data as JSON: /api/errors/9e79637db162e948. Report an issue: GitHub.

Appendix: source

Thrown at dex-tools/src/main/java/com/googlecode/d2j/tools/jar/InvocationWeaver.java:169

                break;
            case Type.BYTE:
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
                break;
            case Type.VOID:
                mv.visitInsn(ACONST_NULL);
                break;
        }
    }

    static private void unBox(Type orgRet, Type nRet, MethodVisitor mv) {
        if (orgRet.equals(nRet)) {
            return;
        }
        if (orgRet.getSort() == Type.VOID) {
            mv.visitInsn(nRet.getSize() == 1 ? POP : POP2);
        }
        if (nRet.getSort() != Type.OBJECT) {
            throw new RuntimeException("invalid ret type:" + nRet);
        }
        switch (orgRet.getSort()) {
            case Type.OBJECT:
            case Type.ARRAY:
                mv.visitTypeInsn(CHECKCAST, orgRet.getInternalName());
                break;
            case Type.INT:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Number");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I", false);
                break;
            case Type.FLOAT:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Number");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "floatValue", "()F", false);
                break;
            case Type.LONG:
                mv.visitTypeInsn(CHECKCAST, "java/lang/Number");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "longValue", "()J", false);
                break;

View on GitHub (pinned to b5bda4fb49)