{"record":{"id":"480bbbe6a2f7d9ec","repo":"kovidgoyal/kitty","slug":"terminal-sent-a-duplicate-drag-data-request","errorCode":null,"errorMessage":"terminal sent a duplicate drag data request","messagePattern":"terminal sent a duplicate drag data request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/dnd/drag.go","lineNumber":281,"sourceCode":"\tif errname == \"\" { // cancel drag\n\t\tdnd.lp.QueueDnDData(DC{Type: 'E', Y: -1})\n\t} else {\n\t\tdnd.lp.QueueDnDData(DC{Type: 'E', Payload: []byte(errname)})\n\t}\n\tdnd.reset_drag()\n}\n\nfunc (dnd *dnd) handle_data_request(idx int) (err error) {\n\tif idx < 0 || idx >= len(dnd.drag_status.offered_mimes) {\n\t\tdnd.finish_drag(\"EINVAL\")\n\t\treturn fmt.Errorf(\"terminal asked for drag data from MIME list with out of bounds index: %d\", idx)\n\t}\n\tmime := dnd.drag_status.offered_mimes[idx]\n\tds := dnd.drag_sources[mime]\n\tfor _, dr := range dnd.drag_status.data_requests {\n\t\tif dr.index == idx {\n\t\t\tdnd.finish_drag(\"EINVAL\")\n\t\t\treturn fmt.Errorf(\"terminal sent a duplicate drag data request\")\n\t\t}\n\t}\n\tdr := &data_request{drag_source: ds, index: idx}\n\tif ds.path == \"\" {\n\t\tdnd.lp.QueueDnDData(DC{Type: 'e', Y: idx, Payload: utils.UnsafeStringToBytes(base64.RawStdEncoding.EncodeToString(ds.data))})\n\t\tdnd.lp.QueueDnDData(DC{Type: 'e', Y: idx}) // EOF\n\t\treturn\n\t} else {\n\t\tif ds.file != nil {\n\t\t\tds.file.Close()\n\t\t}\n\t\tif ds.file, err = os.Open(ds.path); err != nil {\n\t\t\tdnd.finish_drag(\"EIO\")\n\t\t\treturn err\n\t\t}\n\t}\n\tdnd.drag_status.data_requests = append(dnd.drag_status.data_requests, dr)\n\treturn dnd.send_data_for_data_request(len(dnd.drag_status.data_requests) - 1)","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/dnd/drag.go#L263-L299","documentation":"The terminal requested drag data for a MIME index it already requested earlier in the same drag. The kitten treats a repeated request as a protocol violation, finishes the drag with EINVAL, and errors out.","triggerScenarios":"handle_data_request receives an idx already present in drag_status.data_requests — e.g. the terminal re-sent the request because the first response was lost or it mishandles the queue.","commonSituations":"Protocol version skew between kitten and terminal, terminal retrying after a dropped response, or a bug in request bookkeeping during rapid drag interactions.","solutions":["Update kitty so kitten and terminal run matching protocol code","Retry the drag operation — transient duplicates can occur if output was truncated","Report upstream with a debug log of the escape sequences if reproducible"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"Treat as transient: catch the error, tear down drag state via reset_drag(), and let the user retry the drag.","preventionTips":["Keep kitten and terminal versions matched","Avoid extremely rapid repeated drag attempts that race request bookkeeping"],"tags":["dnd","drag-and-drop","duplicate-request","kitty"],"backgroundTag":"duplicate-request","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}