apache/cordova-android · error · IllegalArgumentException
Unsupported keycode: ${keyCode}
Error message
Unsupported keycode: ${keyCode} What it means
CordovaWebViewImpl.setButtonPlumbedToJs(int keyCode, boolean override) whitelists exactly four Android keycodes: KEYCODE_VOLUME_UP (24), KEYCODE_VOLUME_DOWN (25), KEYCODE_BACK (4), and KEYCODE_MENU (82). Every other keycode falls into the switch's default branch and throws IllegalArgumentException. The built-in callers — CoreAndroid's back-button override and overrideButton("volumeup"/"volumedown"/"menubutton") — only ever pass supported codes, so this is reachable only from plugin or app code calling the CordovaWebView API directly with an unlisted keycode.
Source
Thrown at framework/src/org/apache/cordova/CordovaWebViewImpl.java:420
appPlugin.fireJavascriptEvent(event);
}
@Override
public void setButtonPlumbedToJs(int keyCode, boolean override) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
// TODO: Why are search and menu buttons handled separately?
if (override) {
boundKeyCodes.add(keyCode);
} else {
boundKeyCodes.remove(keyCode);
}
return;
default:
throw new IllegalArgumentException("Unsupported keycode: " + keyCode);
}
}
@Override
public boolean isButtonPlumbedToJs(int keyCode) {
return boundKeyCodes.contains(keyCode);
}
@Override
public Object postMessage(String id, Object data) {
return pluginManager.postMessage(id, data);
}
// Engine method proxies:
@Override
public String getUrl() {
return engine.getUrl();
}View on GitHub (pinned to 7c1e190064)
Solutions
- Pass only KeyEvent.KEYCODE_BACK, KEYCODE_MENU, KEYCODE_VOLUME_UP, or KEYCODE_VOLUME_DOWN.
- If you need a different hardware key, intercept it yourself by overriding dispatchKeyEvent/onKeyDown in the Activity or a custom View — Cordova's plumbing API will not carry it.
- If the keycode arrives from external data, whitelist-check it (see type guard) before calling setButtonPlumbedToJs.
Example fix
// before
webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_HOME, true); // throws IllegalArgumentException
// after
if (isPlumbableKeyCode(keyCode)) {
webView.setButtonPlumbedToJs(keyCode, true);
} else {
// handle this key in your own dispatchKeyEvent/onKeyDown instead
} Defensive patterns
Strategy: type-guard
Type guard
private static final Set<Integer> PLUMBABLE_KEY_CODES = new HashSet<>(Arrays.asList(
KeyEvent.KEYCODE_BACK, // 4
KeyEvent.KEYCODE_MENU, // 82
KeyEvent.KEYCODE_VOLUME_UP, // 24
KeyEvent.KEYCODE_VOLUME_DOWN // 25
));
static boolean isPlumbableKeyCode(int keyCode) {
return PLUMBABLE_KEY_CODES.contains(keyCode);
} Try / catch
// Only when the keycode is dynamic and you cannot pre-filter:
try {
webView.setButtonPlumbedToJs(keyCode, override);
} catch (IllegalArgumentException e) {
LOG.w(TAG, "Key not plumbable to JS, ignoring: " + keyCode);
} Prevention
- Treat setButtonPlumbedToJs as supporting exactly four keys: BACK, MENU, VOLUME_UP, VOLUME_DOWN.
- Always use KeyEvent.KEYCODE_* constants, never raw ints or values received from JavaScript.
- For TV remotes, media keys, or hardware buttons outside the whitelist, implement your own dispatchKeyEvent/onKeyDown handling.
When it happens
Trigger: A plugin calls webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_HOME, true), or passes KEYCODE_SEARCH, KEYCODE_CAMERA, KEYCODE_APP_SWITCH, KEYCODE_DPAD_* (Android TV remotes), KEYCODE_MEDIA_*, or a raw int copied from elsewhere instead of a KeyEvent constant.
Common situations: Android TV / set-top-box plugins trying to plumb remote-control keys through Cordova; code ported from older Cordova forks where extra buttons seemed interceptable; keycodes received from JavaScript or config data passed straight into the native API without validation.
Related errors
- Failed to install apk to target: ${output}
- Failed to create webview.
- ${filePath}: Missing key required "${key}"
- Expected Android Build Tools version >= ${cordovaConfig.MIN_
- Keystore file does not exist: ${storeFile.getAbsolutePath()}
AI-assisted analysis of apache/cordova-android@7c1e190064 (2026-08-22).
Data as JSON: /api/errors/63fdf827bbc92341.
Report an issue: GitHub.