go-delve/delve · error
cannot use %s as 'substitutePath' of type {"from":string, "t
Error message
cannot use %s as 'substitutePath' of type {"from":string, "to":string} What it means
Each element of the launch/attach config's substitutePath array must be a JSON object with string fields 'from' and 'to'. A JSON value of the wrong type (e.g. a string, number, or array) appeared where such an object was expected, so custom UnmarshalJSON returns this descriptive error instead of the raw Go type error.
Source
Thrown at service/dap/types.go:255
// For example, mapping with empty 'to' can be used to work with binaries with trimmed paths.
type SubstitutePath struct {
// The local path to be replaced when passing paths to the debugger.
From string `json:"from,omitempty"`
// The remote path to be replaced when passing paths back to the client.
To string `json:"to,omitempty"`
}
func (m *SubstitutePath) UnmarshalJSON(data []byte) error {
// use custom unmarshal to check if both from/to are set.
type tmpType struct {
From *string
To *string
}
var tmp tmpType
if err := json.Unmarshal(data, &tmp); err != nil {
if _, ok := err.(*json.UnmarshalTypeError); ok {
return fmt.Errorf(`cannot use %s as 'substitutePath' of type {"from":string, "to":string}`, data)
}
return err
}
if tmp.From == nil || tmp.To == nil {
return errors.New("'substitutePath' requires both 'from' and 'to' entries")
}
*m = SubstitutePath{*tmp.From, *tmp.To}
return nil
}
// AttachConfig is the collection of attach request attributes recognized by DAP implementation.
// 'processId' and 'waitFor' are mutually exclusive, and can't be specified at the same time.
type AttachConfig struct {
// Acceptable values are:
// "local": attaches to the local process with the given ProcessID.
// "remote": expects the debugger to already be running to "attach" to an in-progress debug session.
//
// Default is "local".View on GitHub (pinned to a23773e6c3)
Solutions
- Make every substitutePath entry an object: {"from":"<remote>","to":"<local>"}
- Ensure both 'from' and 'to' are present string values (missing fields give a related error)
- Validate launch.json against the DAP/delve schema in your editor
- Quote values as strings — numbers and booleans are rejected
Example fix
// before
"substitutePath": ["/remote/src"]
// after
"substitutePath": [{"from": "/remote/src", "to": "/local/src"}] Defensive patterns
Strategy: validation
Validate before calling
func validSubstitutePath(sp []json.RawMessage) error {
for _, r := range sp {
var o map[string]any
if err := json.Unmarshal(r, &o); err != nil { return err }
f, okF := o["from"].(string); t, okT := o["to"].(string)
if !okF || !okT { return fmt.Errorf("entry %s must be {from:string,to:string}", r) }
}
return nil
} Type guard
func isSubstitutePathEntry(v any) bool {
m, ok := v.(map[string]any); if !ok { return false }
_, okF := m["from"].(string); _, okT := m["to"].(string)
return okF && okT
} Try / catch
if _, err := unmarshalLaunchAttachArgs(raw); err != nil { if strings.Contains(err.Error(), "substitutePath") { /* fix launch.json to object entries */ } return err } Prevention
- Always model substitutePath as an array of {from,to} objects
- Enable launch.json schema validation in your editor
- Migrate legacy string-array configs explicitly
When it happens
Trigger: onLaunchRequest/onAttachRequest where substitutePath contains a non-object entry, e.g. "substitutePath": ["/a"] or [ {"from":1,"to":"/b"} ].
Common situations: Users copying old string-array substitutePath syntax from other debuggers, hand-edited launch.json, or schema-less editors not validating the object shape.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- cannot unmarshal %v into %q of type %v
- cannot unmarshal %v into "buildFlags" of type []string or st
- count/len must be a positive integer
- expected argument after -size
- size must be a positive integer (<=8)
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/66d2eb976d0dfd9a.
Report an issue: GitHub.