go-delve/delve · error

malformed data ID: %q

Error message

malformed data ID: %q

What it means

A DAP data breakpoint's DataId must be the string '<goid>,<frame>,<expression>' (three comma-separated parts). The submitted DataId did not have exactly three comma-separated components, so Delve cannot decode it.

Source

Thrown at service/dap/server.go:1990

	})
}

const dataBpPrefix = "dataBreakpoint"

func (s *Session) onSetDataBreakpointRequest(request *dap.SetDataBreakpointsRequest) {
	breakpoints := s.setBreakpoints(s.getWatchpoints(), len(request.Arguments.Breakpoints), func(i int) *bpMetadata {
		want := request.Arguments.Breakpoints[i]
		return &bpMetadata{
			name:         fmt.Sprintf("%s %s", dataBpPrefix, want.DataId),
			condition:    want.Condition,
			hitCondition: want.HitCondition,
			logMessage:   "",
		}
	}, func(i int) (*bpLocation, error) {
		want := request.Arguments.Breakpoints[i]
		v := strings.SplitN(want.DataId, ",", 3)
		if len(v) != 3 {
			return nil, fmt.Errorf("malformed data ID: %q", want.DataId)
		}
		goid, err1 := strconv.ParseInt(v[0], 0, 64)
		frame, err2 := strconv.ParseInt(v[1], 0, 64)
		if err1 != nil || err2 != nil {
			return nil, fmt.Errorf("malformed data ID: %q", want.DataId)
		}
		var wtype api.WatchType
		switch want.AccessType {
		case "read":
			wtype = api.WatchRead
		case "write":
			wtype = api.WatchWrite
		case "readWrite":
			wtype = api.WatchRead | api.WatchWrite
		default:
			return nil, fmt.Errorf("unknown access type: %q", want.AccessType)
		}
		return &bpLocation{

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Use the dataId string exactly as returned in Variable results from a previous variables request
  2. Re-fetch scopes/variables after a restart and re-create data breakpoints from fresh IDs
  3. Ensure no commas inside the expression part break the 3-part format

Example fix

// before
{"breakpoints":[{"dataId":"42"}]}
// after: goid,frame,expr as returned by DAP variables
{"breakpoints":[{"dataId":"1,0,myVar","accessType":"write"}]}
Defensive patterns

Strategy: type-guard

Validate before calling

func validDataId(id string) bool { parts := strings.Split(id, ","); return len(parts) == 3 }

Type guard

func isWellFormDataId(id string) bool {
  v := strings.Split(id, ",")
  if len(v) != 3 { return false }
  _, e1 := strconv.ParseInt(v[0], 0, 64)
  _, e2 := strconv.ParseInt(v[1], 0, 64)
  return e1 == nil && e2 == nil
}

Try / catch

if err := setDataBreakpoints(req); err != nil { if strings.Contains(err.Error(), "malformed data ID") { req.Breakpoints = refreshDataIdsFromVariables(); retry } }

Prevention

When it happens

Trigger: setDataBreakpoints request whose Arguments.Breakpoints[i].DataId is not produced by a previous scopes/variables call (i.e. not of the form 'goid,frame,expr').

Common situations: A client fabricating data breakpoint IDs instead of echoing back the dataId provided in Variable responses, or IDs from an older session/target after restart.

Understand the failure class

Related errors


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