kovidgoyal/kitty · error

Failed to load output from custom processor %#v with error:

Error message

Failed to load output from custom processor %#v with error: %w

What it means

The CustomizeProcessing custom processor ran successfully but its stdout was not valid JSON deserializable into []Mark. json.Unmarshal failed, meaning output was empty, truncated, or not a JSON array of mark objects.

Source

Thrown at kittens/hints/marks.go:687

		stdout, stderr := bytes.Buffer{}, bytes.Buffer{}
		cmd.Stdout, cmd.Stderr = &stdout, &stderr
		err = cmd.Run()
		if err != nil {
			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}

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Send all logging to stderr and only the marks JSON array to stdout
  2. Validate output with: my_processor.py < input.json | jq 'type' — must be 'array'
  3. Match the Mark schema: array of objects with start/end index fields

Example fix

# before
print('processing...')  # stdout pollution
print(json.dumps(marks))
# after
print('processing...', file=sys.stderr)
print(json.dumps(marks))
Defensive patterns

Strategy: validation

Validate before calling

out, err := runProcessor(input)
if err == nil {
    if !json.Valid(out) { err = errors.New("processor stdout not JSON") }
}

Try / catch

On 'Failed to load output from custom processor', dump raw stdout for inspection and fall back to built-in hints.

Prevention

When it happens

Trigger: Custom processor printing logs/diagnostics to stdout instead of stderr, emitting a JSON object instead of an array, or producing no output at all.

Common situations: Debug print statements left in the processor that pollute stdout; processor returning an object {'marks': []}; older processor output format.

Related errors


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