kovidgoyal/kitty · error

Custom processor %#v produced invalid mark output with error

Error message

Custom processor %#v produced invalid mark output with error: %w

What it means

After JSON parsing succeeded, adjust_python_offsets rejected the marks: indices were out of range or inconsistent with the sanitized screen text. Custom processor mark offsets must point into the text it was given.

Source

Thrown at kittens/hints/marks.go:691

			var e *exec.ExitError
			if errors.As(err, &e) && e.ExitCode() == 2 {
				err = run_basic_matching()
				if err != nil {
					return
				}
				goto process_answer
			} else {
				return "", nil, nil, fmt.Errorf("Failed to run custom processor %#v with error: %w\n%s", opts.CustomizeProcessing, err, stderr.String())
			}
		}
		ans = make([]Mark, 0, 32)
		err = json.Unmarshal(stdout.Bytes(), &ans)
		if err != nil {
			return "", nil, nil, fmt.Errorf("Failed to load output from custom processor %#v with error: %w", opts.CustomizeProcessing, err)
		}
		err = adjust_python_offsets(sanitized_text, ans)
		if err != nil {
			return "", nil, nil, fmt.Errorf("Custom processor %#v produced invalid mark output with error: %w", opts.CustomizeProcessing, err)
		}
	} else if opts.Type == "hyperlink" {
		ans = hyperlinks
	} else if opts.Type == "word" {
		ans = mark_words(sanitized_text, opts)
	} else {
		err = run_basic_matching()
		if err != nil {
			return
		}
	}
process_answer:
	if len(ans) == 0 {
		return "", nil, nil, &ErrNoMatches{Type: opts.Type, Pattern: used_pattern}
	}
	largest_index := ans[len(ans)-1].Index
	offset := max(0, opts.HintsOffset)
	if opts.PrefixFree {

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Compute mark offsets against the exact text passed in on stdin, after kitten's sanitization
  2. Clamp all start/end indices to [0, len(text)] and ensure start <= end
  3. Add unit tests in kitty's hints tests (see TestPrefixFreeHints) comparing offsets against the input

Example fix

# before
mark['start'] = raw_index
# after
mark['start'] = min(max(raw_index, 0), len(sanitized_text))
Defensive patterns

Strategy: validation

Validate before calling

for _, m := range marks {
    if m.Start < 0 || m.End > len(text) || m.Start > m.End { return errors.New("mark out of range") }
}

Try / catch

Catch 'produced invalid mark output' and re-run with builtin matcher; log offending offsets.

Prevention

When it happens

Trigger: Marks with start/end beyond the input text length, negative indices, or offsets computed against different text (e.g. before kitten's sanitization or using code points vs bytes inconsistently).

Common situations: Processor computing offsets on the raw text while kitten passes sanitized text; off-by-one bugs; treating tabs/escape sequences differently.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/f1211711f6c3fbd4. Report an issue: GitHub.