{"record":{"id":"8a518c81413accff","repo":"kovidgoyal/kitty","slug":"too-many-hyperlinks-discarding-hyperlink-s","errorCode":null,"errorMessage":"Too many hyperlinks, discarding hyperlink: %s","messagePattern":"Too many hyperlinks, discarding hyperlink: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kitty/hyperlink.c","lineNumber":152,"sourceCode":"\nhyperlink_id_type\nget_id_for_hyperlink(Screen *screen, const char *id, const char *url) {\n    if (!url) return 0;\n    HyperLinkPool *pool = (HyperLinkPool *)screen->hyperlink_pool;\n    static char key[MAX_KEY_LEN] = {0};\n    int keylen = snprintf(key, MAX_KEY_LEN - 1, \"%.*s:%s\", MAX_ID_LEN, id ? id : \"\", url);\n    if (keylen < 0) keylen = strlen(key);\n    else keylen = MIN(keylen, MAX_KEY_LEN - 2); // snprintf returns how many chars it would have written in case of truncation\n    key[keylen] = 0;\n    hyperlink_map_itr itr = vt_get(&pool->map, key);\n    if (!vt_is_end(itr)) return itr.data->val;\n    if (pool->array.count >= HYPERLINK_MAX_NUMBER - 1) {\n        screen_garbage_collect_hyperlink_pool(screen);\n        if (pool->array.count >= HYPERLINK_MAX_NUMBER - 128) {\n            log_error(\"Too many hyperlinks, discarding hyperlinks in scrollback\");\n            _screen_garbage_collect_hyperlink_pool(screen, false);\n            if (pool->array.count >= HYPERLINK_MAX_NUMBER) {\n                log_error(\"Too many hyperlinks, discarding hyperlink: %s\", key);\n                return 0;\n            }\n        }\n    }\n    if (!pool->array.count) pool->array.count = 1; // First id must be 1\n    ensure_space_for(&(pool->array), items, hyperlink, pool->array.count + 1, capacity, 256, false);\n    hyperlink_id_type new_id = pool->array.count++;\n    pool->array.items[new_id] = dupstr(key, keylen);\n    if (vt_is_end(vt_insert(&pool->map, pool->array.items[new_id], new_id))) fatal(\"Out of memory\");\n    // If there have been a lot of hyperlink adds do a garbage collect so as\n    // not to leak too much memory over unused hyperlinks\n    if (++pool->adds_since_last_gc > 8192) screen_garbage_collect_hyperlink_pool(screen);\n    return new_id;\n}\n\nconst char *\nget_hyperlink_for_id(const HYPERLINK_POOL_HANDLE handle, hyperlink_id_type id, bool only_url) {\n    HyperLinkPool *pool = (HyperLinkPool *)handle;","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/hyperlink.c#L134-L170","documentation":"Even after discarding scrollback hyperlinks the pool is completely full (>= HYPERLINK_MAX_NUMBER), so the new hyperlink gets id 0 and is not clickable. The offending URI is printed.","triggerScenarios":"Thousands of simultaneously live (on-screen) unique OSC 8 hyperlinks exhausting the pool so no id can be allocated.","commonSituations":"Applications rendering huge linkified documents with massive numbers of distinct active links.","solutions":["Reduce simultaneously displayed unique links in the application","Clear the screen/scrollback to release hyperlink ids","Update kitty","File an upstream issue against the app emitting the flood of links"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Limit unique simultaneously-visible links","Reuse OSC 8 id parameters for repeated URLs"],"tags":["kitty","hyperlinks","osc8","resource-limits"],"backgroundTag":"resource-pool-exhausted","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}