pxb1988/dex2jar · error · RuntimeException

Encountered RESTART_LOCAL on new v

Error message

Encountered RESTART_LOCAL on new v

What it means

While decoding the debug_info_item state machine, a DBG_RESTART_LOCAL opcode refers to a register that has no previous 'start local' entry in lastEntryForReg. The reader cannot 'restart' a local that was never started, so it throws a RuntimeException naming the offending register. This indicates a malformed or non-standard debug section.

Solutions

  1. Recompile/re-dex the source with d8/dx to regenerate valid debug info
  2. Strip debug info (d8 --no-debug-info or dx --no-debug-info / --no-local-info) so the debug state machine is never walked
  3. Patch the dex's debug_info_item so every DBG_RESTART_LOCAL follows a matching start for that register
  4. As a last resort, patch the library to log-and-skip instead of throwing if you accept losing that local's info

Example fix

// before
// dx --debug classes.jar  # keeps fragile debug info
// after
// dx --no-local-info --output classes.dex classes.jar
Defensive patterns

Strategy: validation

Validate before calling

// Prefer pre-validating the toolchain output:
// d8 --release --no-debug-info avoids DBG_RESTART_LOCAL processing entirely.
// There is no cheap pre-check for debug-info consistency; strip debug info instead:
// Process.run("d8", "--release", "--no-debug-info", "--output", outDir, input)
null

Try / catch

try {
    new DexFileReader(file).accept(visitor);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Encountered RESTART_LOCAL")) {
        // fall back to a no-debug-info build of the same dex
        return parseWithDebugInfoStripped(file);
    }
    throw e;
}

Prevention

When it happens

Trigger: Processing dex bytecode whose debug info contains DBG_RESTART_LOCAL for a register with no prior DBG_START_LOCAL/DBG_START_LOCAL_EXTENDED — typically a corrupted debug_info_item or output from a non-conforming dex compiler/obfuscator.

Common situations: Reading dex files produced by aggressive obfuscators that strip or rewrite debug info; hand-patched dex; tools like dex2jar converting dex with broken debug state during translate/debug reads.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at dex-reader/src/main/java/com/googlecode/d2j/reader/DexFileReader.java:515

                int nameIdx = readStringIndex(in);
                int typeIdx = readStringIndex(in);
                int sigIdx = readStringIndex(in);
                String name = getString(nameIdx);
                String type = getType(typeIdx);
                String signature = getString(sigIdx);
                DEBUG_DEBUG("Start: v%d :%s, %s // %s", reg, name, type, signature);
                LocalEntry le = new LocalEntry(name, type, signature);
                order(labelMap, address);
                dcv.visitStartLocal(reg, labelMap.get(address), name, type, signature);
                lastEntryForReg[reg] = le;
            }
                break;

            case DBG_RESTART_LOCAL: {
                int reg = readULeb128i(in);
                LocalEntry le = lastEntryForReg[reg];
                if (le == null) {
                    throw new RuntimeException("Encountered RESTART_LOCAL on new v" + reg);
                }
                if (le.signature == null) {
                    DEBUG_DEBUG("Start: v%d :%s, %s", reg, le.name, le.type);
                } else {
                    DEBUG_DEBUG("Start: v%d :%s, %s // %s", reg, le.name, le.type, le.signature);
                }
                order(labelMap, address);
                dcv.visitRestartLocal(reg, labelMap.get(address));
            }
                break;

            case DBG_END_LOCAL: {
                int reg = readULeb128i(in);
                LocalEntry le = lastEntryForReg[reg];
                if (le == null) {
                    throw new RuntimeException("Encountered RESTART_LOCAL on new v" + reg);
                }
                if (le.signature == null) {

View on GitHub (pinned to b5bda4fb49)