-
-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug(web): TypeError: Cannot read property 'layout' of null #6898
Comments
Looking into this bug, it would appear that this arises with KMW believes that there is no active keyboard:
(Sentry likes to omit our internal libraries in its default reporting view.) Upon inspecting the relevant call path... I see that it's entirely possible to reach this point with a I wonder if this is related to #6703 in any manner? That said, there's clearly something 'funny' going on here... as to get the error above, the user had to interact with an OSK. Which implies there should've been an active keyboard at the time of the keypress. |
Or possibly #6978, given its noted repro? (But via globe key, rather than shift) |
Please include text rather than screenshot of stack trace (so we can search it in future!)
|
Not that it's terribly informative, but there's one interesting thing I just noticed when looking through the Sentry event logs. This is happening down the chain of calls for an OSK event listener. As such, Sentry is logging that listener's event object for us, yielding data like this, as seen in some of the events:
I'd like to highlight that For contrast, some of the other Sentry events log something like this instead:
Note the lack of What this tells us: this error is happening for multiple different active keyboards, with a fully-loaded OSK at the time that the event was received. Why the activeKeyboard (or, at least, its layout) is going |
Also, I have not had any success reproducing this by trying something similar to #6978 (comment). |
Sentry issue: KEYMAN-WEB-H |
Of interest, for what it's worth: Using the "Predictive Text: robust testing" test page in Chrome...
Result:
Of note: if done on a keyboard without active predictive text...
(Hence the Sentry issue I just linked above.) |
Of course, the question is what might have put KMW into such a state within the Android Keyman engine. |
So, I had an idea and investigated keyboard-loading Sentry reports for Keyman for Android; this has resulted in #7412. After all, failure to load a keyboard could possibly put KMW into a null-keyboard state. Unfortunately, I do not believe #7412 is perfectly correlated, or even sufficient to explain all instances of this bug report. To wit: #7412 event reports: For this Sentry event: I don't have to go hunting to merge extra events to realize that the numbers for #7412 are markedly lower than for this issue's bug. Even if this issue's bug were triggered multiple times by the one from #7412... note the user counts. That is the definitive proof that #7412 cannot provide the full picture - this issue's bug has affected over four times as many users! |
The only spot in KMW code I can find that sets the keyman/web/source/keyboards/kmwkeyboards.ts Lines 583 to 584 in 0191d9a
It's evaluated when we're dynamically loading the script for a not-yet-loaded keyboard. Since I've neglected to point out why I'm chasing this point up 'til now...
Compare with: keyman/common/web/input-processor/src/text/inputProcessor.ts Lines 270 to 271 in 0191d9a
There's... not really any other way to read this error. Likewise, for the other Sentry issue linked to this one: keyman/common/core/web/keyboard-processor/src/text/kbdInterface.ts Lines 1073 to 1075 in 94214c0
Same reasoning. |
Via a temporary local build, I was able to verify that the mobile app will not show an OSK if it is never able to successfully load a keyboard (so, if none ever succeeds). There must have been an active OSK at some point in the keyboard's lifecycle to get the callstacks we're seeing. |
I've managed to trigger a set of three at one point when doing mashes while quick-swapping the keyboard (via globe-key taps, 2 keyboards installed), but nothing consistent enough to call a repro. https://sentry.io/organizations/keyman/issues/2776546156/events/ecfa376e541948239280ce41ee41dbca/ (+ the two previous) Minor, possibly-relevant detail: it was not the first swap after the app was loaded. At any rate, it occurred on the test device either during or immediately after a series of keyboard swaps. |
Yeah. Definitely not a reliable repro; I haven't seen it again since. I did get a few repros for other issues / events related to other issues, though. I'm starting to wonder if it's a matter of filesystem lag during a keyboard load. Like, if a load goes "more asynchronous" than usual when trying to load a script tag as part of a keyboard swap, that'd leave a period where |
Easiest way to make this far more consistent: induce an artificial delay within KMW when keyboard swapping. The following event was generated from such a build: https://sentry.io/organizations/keyman/issues/2776546156/events/7eeba213291849c6a0c9613978ef203c/ That said, this will only work for the first such quick-swap to new keyboards. This can be reset by longpressing globe and using the picker menu, though, and think I remember accidentally doing that a time or two during the "mash" session that led to the previous comment. Here's how things look with the artificial repro: (Occurred after the 'quick swap' globe key tap, then pressing 't' on the observed keyboard layout [before the swap completes].) It should be obvious that Typing any output key while in this state will generate either this issue's original error or the other error from #6898 (comment). It's a web-internal issue. The question then is how best to handle these scenarios. The old keyboard lingers on touch devices because we force-set the OSK to be permanently visible once a keyboard has properly been loaded. For the common case, this is good - there's less "flashing" in and out as a result of that decision. But... if we do find ourselves in an intermediate state... this error may arise. I'm not sure if it's actually a priority to resolve, as this appears not to affect any common-case user scenarios - at least not severely. I mean, if we're using keyboard quick-swapping, it auto-resolves after the first swap - so even if a user just has two keyboards installed and does a lot of code-switching, there's only a bit of an initial "stumble" before everything feels stable. (Which is probably why we haven't received any corresponding user reports of the issue.) The cleanest possible way forward I can think of is to pre-load whatever keyboard is 'next' in the quick-swap position. Preloading just one shouldn't come with too high of a memory footprint, and it's easy enough to let that happen in the background asynchronously. Slightly less clean would be to disable all interactivity during the swap. All of this said, if I've properly discerned the cause of the issue... there's the matter that in theory, we probably should see this on iOS as well, even if only in the context of the system keyboard. |
I can easily provide a branch for the artificial repro if desired. It would affect the full Web, Android, and iOS set. |
Good analysis. Preloading may be a simple enough mitigation -- although possibly not desirable for very complex keyboards such as Vietnamese Telex or Hieroglyphics.
Sounds good to me -- mark it as "DO NOT MERGE" and give it a "test:" prefix. |
See #7426. |
So, coming back to this with a fresh perspective, I had an idea. It's a bit of a pivot, but I believe it'll handle the majority of the error reports we're getting. See #7543 for the details. I'm pretty sure it's a better solution than the previous suggestion would have been, too. Things would get weird if a key on keyboard 1 didn't exist on the default layer of keyboard 2, preloaded or not. |
Note: the changes of #7543 do nothing to handle any similar cases for key events from physical keyboards - neither in 'native' nor in 'embedded' mode. Those would need more specialized code to handle correctly.
I'd say we can probably consider this fixed once hardware keystrokes are handled well by non-embedded use cases. |
From a comment on that PR:
Note also that in the present implementation, physical keystrokes do not set |
I think it'd be good to split handling of hardware keystrokes into a separate issue, given it is likely to be an infrequent one, and mark it for future resolution, and then resolve this and the corresponding Sentry issues. What do you think? |
While this probably resolves the first (fat-finger) one (since it doesn't trigger on desktop devices), the other Sentry issue may not be reasonably resolved.
Infrequent != resolved, sadly.
That part's pretty reasonable, though. |
Sentry Issue: KEYMAN-WEB-J
Note that this error only happens within Keyman for Android. However it is an error raised by Keyman Engine for Web.
The text was updated successfully, but these errors were encountered: