go-delve/delve · error

could not find rule for %q

Error message

could not find rule for %q

What it means

When 'config substitutePath <path>' is called with exactly one argument, Delve interprets it as a delete request and searches existing substitutePath rules for a matching client path. If no rule matches, 'could not find rule for %q' is returned. Deleting requires an exact match of an existing rule's client-side path.

Source

Thrown at service/dap/config.go:81

	argv := config.SplitQuotedFields(rest, '"')
	if len(argv) == 2 && argv[0] == "-clear" {
		argv = argv[1:]
	}
	switch len(argv) {
	case 0:
		// do nothing, let caller show the current list of substitute path rules
		return nil
	case 1: // delete substitute-path rule
		for i := range args.substitutePathClientToServer {
			if args.substitutePathClientToServer[i][0] == argv[0] {
				copy(args.substitutePathClientToServer[i:], args.substitutePathClientToServer[i+1:])
				args.substitutePathClientToServer = args.substitutePathClientToServer[:len(args.substitutePathClientToServer)-1]
				copy(args.substitutePathServerToClient[i:], args.substitutePathServerToClient[i+1:])
				args.substitutePathServerToClient = args.substitutePathServerToClient[:len(args.substitutePathServerToClient)-1]
				return nil
			}
		}
		return fmt.Errorf("could not find rule for %q", argv[0])
	case 2: // add substitute-path rule
		for i := range args.substitutePathClientToServer {
			if args.substitutePathClientToServer[i][0] == argv[0] {
				args.substitutePathClientToServer[i][1] = argv[1]
				args.substitutePathServerToClient[i][0] = argv[1]
				return nil
			}
		}
		args.substitutePathClientToServer = append(args.substitutePathClientToServer, [2]string{argv[0], argv[1]})
		args.substitutePathServerToClient = append(args.substitutePathServerToClient, [2]string{argv[1], argv[0]})

	default:
		return errors.New("too many arguments to \"config substitutePath\"")
	}
	return nil
}

func configureSetShowPprofLabels(args *launchAttachArgs, rest string) error {

View on GitHub (pinned to a23773e6c3)

Solutions

  1. Run 'config substitutePath' with no arguments to list current rules and copy the exact client path.
  2. Match the path byte-for-byte, including case and absence/presence of trailing slashes.
  3. If the rule came from launch.json, remove it there (in-session rules reset between sessions).
  4. Add the rule first with two arguments ('config substitutePath /client /server') before attempting deletion.

Example fix

// before
debugConsole> config substitutePath /Src
// after (exact existing rule)
config substitutePath /src
Defensive patterns

Strategy: validation

Validate before calling

// list current rules before deleting:
out := runEval("config substitutePath")
existing := parseClientPaths(out)
if !existing[clientPath] {
    return fmt.Errorf("no rule for %q; exact match required", clientPath)
}

Prevention

When it happens

Trigger: Evaluating 'config substitutePath /client/path' where /client/path is not registered (typo, wrong case, never added, or already cleared with -clear).

Common situations: Trying to remove a rule defined in launch.json after a session restart that reset in-session rules; path case mismatch on Windows/case-sensitive mounts; trailing slash differences ('/src' vs '/src/'); assuming rules from a prior debug session persist.

Related errors


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