kovidgoyal/kitty · error

Unknown change type: %#v

Error message

Unknown change type: %#v

What it means

While rendering directory-diff entries, render.go dispatches on each changed item's type string; any value other than the recognized kinds (e.g. 'add', 'remove', 'change', 'rename') reaches the default branch and raises this error with the %#v-formatted type. It indicates the collection of changes contains an entry type the renderer does not know.

Source

Thrown at kittens/diff/render.go:874

			if is_binary {
				if is_img {
					ans, err = image_lines(path, "", screen_size, margin_size, image_size, ans)
				} else {
					ans, err = binary_lines(path, "", columns, margin_size, ans)
				}
			} else {
				ans, err = all_lines(path, columns, margin_size, false, ans)
			}
			if err != nil {
				return err
			}
		case "rename":
			ans, err = rename_lines(path, changed_path, columns, margin_size, ans)
			if err != nil {
				return err
			}
		default:
			return fmt.Errorf("Unknown change type: %#v", item_type)
		}
		return nil
	})
	var ll []*LogicalLine
	if len(ans) > 1 {
		ll = ans[:len(ans)-1]
	} else {
		// Having am empty list of lines causes panics later on
		ll = []*LogicalLine{{line_type: EMPTY_LINE, screen_lines: []*ScreenLine{{}}}}
	}
	return &LogicalLines{lines: ll, title_line_indices: title_line_indices, margin_size: margin_size, columns: columns}, err
}

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Identify the offending item type from the %#v value in the message.
  2. If it comes from git metadata, refresh/regenerate the change list (git status) and retry; typechange entries can be normalized to remove+add.
  3. Update kitty to the latest version in case the type is newly supported.
  4. If calling render() directly, map your change types onto the supported set before rendering.

Example fix

// before
collection.Add("copy", oldPath, newPath)

// after
collection.Add("add", "", newPath)
collection.Add("remove", oldPath, "")
Defensive patterns

Strategy: type-guard

Validate before calling

// Go: whitelist change types before handing a collection to render()
allowed := map[string]bool{"add": true, "remove": true, "change": true, "rename": true}
for _, it := range collection.Items {
    if !allowed[it.Type] {
        return fmt.Errorf("unsupported change type %q; map it to add/remove", it.Type)
    }
}

Type guard

func isSupportedChangeType(t string) bool {
    switch t {
    case "add", "remove", "change", "rename":
        return true
    }
    return false
}

Try / catch

On 'Unknown change type', extract the %#v value from the message, normalize the entry (e.g. copy/typechange -> remove+add), and re-render; log unhandled values for upstream reporting.

Prevention

When it happens

Trigger: A change collection (typically produced from git status parsing or similar) containing an unexpected type string such as 'copy', 'typechange', or an empty/garbage value; extension or newer kitty versions producing types this build's renderer can't handle; custom code feeding render() its own collection.

Common situations: Version skew between components generating the change list and the renderer; git reporting 'T' (typechange) or 'C' (copy) entries that fall outside the handled set; third-party tools reusing the kitten's render API with richer type vocabularies.

Related errors


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