{"record":{"id":"256e16804a6eaa8f","repo":"kovidgoyal/kitty","slug":"custom-draw-tab-function-failed-with-error-e","errorCode":null,"errorMessage":"Custom draw tab function failed with error: {e}","messagePattern":"Custom draw tab function failed with error: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kitty/tab_bar.py","lineNumber":679,"sourceCode":"        log_error(f'Failed to load custom tab_bar.py module with error: {e}')\n        return {}\n\n\n@run_once\ndef load_custom_draw_tab() -> DrawTabFunc:\n    m = load_custom_draw_tab_module()\n    func: DrawTabFunc | None = m.get('draw_tab')\n    if func is None:\n        return draw_tab_with_fade\n\n    @wraps(func)\n    def draw_tab(\n        draw_data: DrawData, screen: Screen, tab: TabBarData, before: int, max_tab_length: int, index: int, is_last: bool, extra_data: ExtraData\n    ) -> int:\n        try:\n            return func(draw_data, screen, tab, before, max_tab_length, index, is_last, extra_data)\n        except Exception as e:\n            log_error(f'Custom draw tab function failed with error: {e}')\n            return draw_tab_with_fade(draw_data, screen, tab, before, max_tab_length, index, is_last, extra_data)\n\n    return draw_tab\n\n\ndef clear_caches() -> None:\n    load_custom_draw_tab.clear_cached()\n    load_custom_draw_tab_module.clear_cached()\n\n\nclass CustomDrawTitleFunc:\n    def __init__(self, data: dict[str, Any], implementation: Callable[[dict[str, Any]], str] | None = None):\n        self._implementation = implementation\n        self._data = {} if implementation is None else data.copy()\n\n    def __str__(self) -> str:\n        if self._implementation is None:\n            return ''","sourceCodeStart":661,"sourceCodeEnd":697,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/tab_bar.py#L661-L697","documentation":"A user-supplied draw_tab function (from tab_bar.py) raised at render time; kitty logs the error and falls back to the built-in draw_tab_with_fade so the tab bar still renders.","triggerScenarios":"The wrapped custom draw_tab in tab_bar.py raises any Exception during tab bar update.","commonSituations":"Runtime bugs in custom tab bar code (division by zero on max_tab_length, None title, API changes to TabBarData fields) that only manifest with real tabs.","solutions":["Check kitty's log for the exact exception from your draw_tab","Guard against edge values: max_tab_length <= 0, missing tab.title, empty extra_data.tabs","Update tab_bar.py to the current kitty tab bar API and test with 0, 1, and many tabs"],"exampleFix":"# before\ndef draw_tab(dd, screen, tab, before, max_tab_length, index, is_last, extra_data):\n    return dd.ascent + len(tab.title) // max_tab_length\n\n# after\ndef draw_tab(dd, screen, tab, before, max_tab_length, index, is_last, extra_data):\n    if max_tab_length < 1:\n        return dd.ascent\n    return dd.ascent + len(tab.title or '') // max_tab_length","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"def draw_tab(dd, screen, tab, before, max_tab_length, index, is_last, extra_data):\n    try:\n        return my_draw(dd, screen, tab, before, max_tab_length, index, is_last, extra_data)\n    except Exception:\n        return draw_tab_with_fade(dd, screen, tab, before, max_tab_length, index, is_last, extra_data)","preventionTips":["Guard against max_tab_length <= 0 and empty/None titles","Test your tab bar with 0, 1, and many tabs before shipping"],"tags":["kitty","tab-bar","customization","runtime-error"],"backgroundTag":"user-plugin-runtime-error","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}