go-delve/delve · error

malformed stop packet: %s (wrong jstopinfo)

Error message

malformed stop packet: %s (wrong jstopinfo)

What it means

Thrown by parseStopPacket when a stop packet carries a 'jstopinfo' extension (debugserver / multiprocess stop info) whose value is not valid hex, so hex.DecodeString fails before JSON parsing. jstopinfo is a hex-encoded JSON array describing per-thread stop reasons; a corrupt encoding means Delve cannot read multi-thread stop state.

Source

Thrown at pkg/proc/gdbserial/gdbserver_conn.go:845

				}
			case "reason":
				sp.reason = string(value)
			case "watch", "awatch", "rwatch":
				sp.watchAddr, err = strconv.ParseUint(string(value), 16, 64)
				if err != nil {
					return false, stopPacket{}, fmt.Errorf("malformed stop packet: %s (wrong watch address)", string(resp))
				}
			case "metype":
				// mach exception type (debugserver extension)
				metype, _ = strconv.Atoi(string(value))
			case "medata":
				// mach exception data (debugserver extension)
				d, _ := strconv.ParseUint(string(value), 16, 64)
				medata = append(medata, d)
			case "jstopinfo":
				jstopinfo, err := hex.DecodeString(string(value))
				if err != nil {
					return false, stopPacket{}, fmt.Errorf("malformed stop packet: %s (wrong jstopinfo)", string(resp))
				}
				parsedJstopInfo := []jsonStopPacket{}
				if err := json.Unmarshal(jstopinfo, &parsedJstopInfo); err != nil {
					return false, stopPacket{}, fmt.Errorf("malformed stop packet: %s (wrong jstopinfo)", string(resp))
				}
				sp.jstopInfo = make(map[int]stopPacket)
				for _, jsp := range parsedJstopInfo {
					threadID := fmt.Sprintf("%d", jsp.Tid)
					newStopPacket := stopPacket{
						threadID: threadID,
						reason:   jsp.Reason,
						sig:      uint8(jsp.Signal),
					}
					parseMachException(&newStopPacket, jsp.Metype, jsp.Medata)
					sp.jstopInfo[jsp.Tid] = newStopPacket
				}
			}
		}

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Reconnect to the target — the packet was likely truncated in transit
  2. Inspect raw traffic with gdbwire logging to confirm corruption source
  3. Update debugserver / the target OS to a version with stable jstopinfo support
  4. Upgrade Delve; handling of debugserver stop-packet extensions improves over releases
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "wrong jstopinfo") {
    // retry once; jstopinfo failures are often transient packet corruption
    if retryErr := reconnect(); retryErr == nil {
        return continueAndCollect()
    }
    // fall back to per-thread stop-info queries
    return queryStopInfoPerThread()
}

Prevention

When it happens

Trigger: A vCont stop reply (typically from Apple debugserver or with multiprocess extensions enabled) contains 'jstopinfo:<value>' where value is not hex — e.g. truncated or corrupted payload.

Common situations: iOS/macOS debugging with debugserver over a flaky USB/Wi-Fi link; stubs that partially implement the jstopinfo extension; packet fragmentation on unreliable transports.

Understand the failure class

Related errors


AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31). Data as JSON: /api/errors/7458ea04d5600cca. Report an issue: GitHub.