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
- Reconnect to the target — the packet was likely truncated in transit
- Inspect raw traffic with gdbwire logging to confirm corruption source
- Update debugserver / the target OS to a version with stable jstopinfo support
- 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
- Use wired, low-loss transports for iOS/device debugging
- Keep debugserver and Delve versions matched
- Enable gdbwire logging to distinguish transient corruption from schema drift
- Have a per-thread qThreadStopInfo fallback path in tooling built on Delve
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- malformed stop packet: %s (wrong watch address)
- wrong response length, expected %d got %d
- malformed response for vCont %s
- malformed stop packet: %s
- unexpected response for vCont %c
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/7458ea04d5600cca.
Report an issue: GitHub.