{"record":{"id":"255f5f1f45f3cd5d","repo":"fyne-io/fyne","slug":"out-of-touchids","errorCode":null,"errorMessage":"out of touchIDs","messagePattern":"out of touchIDs","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/driver/mobile/app/darwin_ios.go","lineNumber":181,"sourceCode":"//export sendTouch\nfunc sendTouch(cTouch, cTouchType uintptr, x, y float32) {\n\tid := -1\n\tfor i, val := range touchIDs {\n\t\tif val == cTouch {\n\t\t\tid = i\n\t\t\tbreak\n\t\t}\n\t}\n\tif id == -1 {\n\t\tfor i, val := range touchIDs {\n\t\t\tif val == 0 {\n\t\t\t\ttouchIDs[i] = cTouch\n\t\t\t\tid = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif id == -1 {\n\t\t\tpanic(\"out of touchIDs\")\n\t\t}\n\t}\n\n\tt := touch.Type(cTouchType)\n\tif t == touch.TypeEnd {\n\t\t// Clear all touchIDs when touch ends. The UITouch pointers are unique\n\t\t// at every multi-touch event. See:\n\t\t// https://github.com/fyne-io/fyne/issues/2407\n\t\t// https://developer.apple.com/documentation/uikit/touches_presses_and_gestures?language=objc\n\t\tfor idx := range touchIDs {\n\t\t\ttouchIDs[idx] = 0\n\t\t}\n\t}\n\n\ttheApp.events.In() <- touch.Event{\n\t\tX:        x,\n\t\tY:        y,\n\t\tSequence: touch.Sequence(id),","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/fyne-io/fyne/blob/8860ee95c356385effa5a7be51adb11c6be9d2b6/internal/driver/mobile/app/darwin_ios.go#L163-L199","documentation":"iOS driver of Fyne's mobile/app package. It maps each active UITouch pointer to a slot in a fixed-size table, var touchIDs [11]uintptr in darwin_ios.go. sendEvent looks up the incoming UITouch pointer, else takes the first zero slot; if all 11 slots hold non-zero pointers it panics with 'out of touchIDs'. The whole table is cleared whenever any touch TypeEnd arrives because UITouch pointers are unique per multi-touch event (Fyne issue #2407).","triggerScenarios":"A 12th simultaneous touch begins while 11 slots are live; or a new UITouch pointer arrives with no free slot because no TypeEnd event has cleared the table yet (dropped/cancelled touches, gesture recognizers swallowing events, automation that never sends TypeEnd).","commonSituations":"Multi-touch apps on iPad (hardware tracks more than 11 pointers); UI-automation and stress tests firing touch bursts without matching end events; custom gesture recognizers that cancel touches without forwarding them.","solutions":["Keep simultaneously tracked touches at 10 or fewer for headroom under the 11-slot table","Ensure every synthesized or intercepted touch eventually delivers a touch.TypeEnd so the table clears","Upgrade Fyne and check release notes for darwin_ios touch handling changes beyond the #2407 fix","If you fork/vendor the driver, enlarge touchIDs or drop unknown touches (log and return) instead of panicking"],"exampleFix":"// before (test harness): 12 begin events, no ends -> panic: out of touchIDs\nfor i := 0; i < 12; i++ {\n\tinjectTouch(uintptr(i), touch.TypeBegin)\n}\n\n// after: stay under 11 slots and always end touches\nconst maxTouches = 10\nfor i := 0; i < maxTouches; i++ {\n\tinjectTouch(uintptr(i), touch.TypeBegin)\n}\nfor i := 0; i < maxTouches; i++ {\n\tinjectTouch(uintptr(i), touch.TypeEnd)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The panic fires on the iOS event thread inside the driver, so a normal\n// recover cannot save the process; wrap app startup so crashes at least\n// produce a labeled report before the app dies.\nfunc runGuarded(a fyne.App) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tlog.Printf(\"driver panic (likely touchIDs exhaustion): %v\", r)\n\t\t\tpanic(r) // re-panic to keep the crash report\n\t\t}\n\t}()\n\ta.Run()\n}","preventionTips":["Cap simultaneous tracked touches in app logic at 10 (table holds 11) so the driver never runs out of slots","In UI automation, always pair every TypeBegin with a TypeEnd (any end event clears the whole table)","Forward cancelled touches from custom gesture recognizers so end events are not lost","Run multi-touch stress tests on real hardware before shipping iPad apps","Track Fyne updates to darwin_ios.go and upgrade; the table-clearing behavior may change"],"tags":["go","ios","uikit","multitouch","panic","mobile"],"backgroundTag":null,"analyzedSha":"8860ee95c356385effa5a7be51adb11c6be9d2b6","analyzedAt":"2026-08-15T22:01:51.624Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}