kovidgoyal/kitty · error

Failed to parse map = %#v with error: %w

Error message

Failed to parse map = %#v with error: %w

What it means

Specialized form of 545 for the 'map' key: kitty keyboard shortcuts in config files are parsed by config.ParseMap in Go. When the map value's syntax is invalid (malformed key mapping, missing action, bad chord syntax), this wrapper reports the raw map string plus the underlying ParseMap error.

Source

Thrown at kitty/conf/generate.py:714

        a('default: return fmt.Errorf("Unknown configuration key: %#v", key)')
        for oname, pname in go_parsers.items():
            ol = oname.lower()
            is_multiple = oname in multiopts
            a(f'case "{ol}":')
            if is_multiple:
                a(f'var temp_val []{go_types[oname]}')
            else:
                a(f'var temp_val {go_types[oname]}')
            a(f'temp_val, err = {pname}')
            a(f'if err != nil {{ return fmt.Errorf("Failed to parse {ol} = %#v with error: %w", val, err) }}')
            if is_multiple:
                a(f'c.{oname} = append(c.{oname}, temp_val...)')
            else:
                a(f'c.{oname} = temp_val')
        if keyboard_shortcuts:
            a('case "map":')
            a('tempsc, err := config.ParseMap(val)')
            a('if err != nil { return fmt.Errorf("Failed to parse map = %#v with error: %w", val, err) }')
            a('c.KeyboardShortcuts = append(c.KeyboardShortcuts, tempsc)')
        a('}')
        a('return}')
    else:
        a('return fmt.Errorf("Unknown configuration key: %#v", key)')
        a('}')
    return '\n'.join(lines)


def main() -> None:
    # To use run it as:
    # kitty +runpy 'from kitty.conf.generate import main; main()' /path/to/kitten/file.py
    import importlib
    import sys

    from kittens.runner import path_to_custom_kitten, resolved_kitten
    from kitty.constants import config_dir

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Read the inner error from ParseMap — it pinpoints the malformed segment of the mapping
  2. Validate the line against kitty's map syntax docs (map key_spec action args)
  3. Test interactively: kitty --debug-config or kitty --debug-keyboard to see if the map parses in the main config layer
  4. Simplify: temporarily comment out maps and re-add one by one to find the offender

Example fix

# before
map ctrl+ page_up scroll

# after
map ctrl+page_up scroll_page_up
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(line, "map ") {
    parts := strings.Fields(line)
    if len(parts) < 3 {
        return fmt.Errorf("map line needs a key spec and an action: %q", line)
    }
}

Type guard

func isValidMapLine(line string) bool {
    p := strings.Fields(line)
    return len(p) >= 3 && p[0] == "map"
}

Try / catch

if err := cfg.Parse("map", mapVal); err != nil {
    if strings.Contains(err.Error(), "Failed to parse map") {
        log.Printf("skipping bad keybinding: %s", mapVal)
        continue
    }
    return err
}

Prevention

When it happens

Trigger: Writing a 'map' line with invalid syntax in kitty.conf, e.g. 'map ctrl+ send_text hello', 'map = ', or chord/action combos ParseMap rejects, when the config is consumed by a Go-based kitten parser.

Common situations: Complex map lines with missing actions, unmatched syntax, or new map grammar from a newer kitty not yet in the generated Go parser; copy-pasted maps with smart quotes or invisible characters; maps using deprecated action names.

Understand the failure class

Related errors


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