termux/termux-app · error · JSONException
All keys have to specify either key or macro
Error message
All keys have to specify either key or macro
What it means
Thrown by the same ExtraKeyButton constructor when a button config object defines NEITHER 'key' nor 'macro'. At least one is required so the button knows what to emit. This usually means the JSON object is empty or only contains display/auxiliary fields.
Source
Thrown at termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeyButton.java:94
* @param extraKeyAliasMap The {@link ExtraKeysConstants.ExtraKeyDisplayMap} that defines the
* aliases for the actual key names.
*/
public ExtraKeyButton(@NonNull JSONObject config, @Nullable ExtraKeyButton popup,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyDisplayMap,
@NonNull ExtraKeysConstants.ExtraKeyDisplayMap extraKeyAliasMap) throws JSONException {
String keyFromConfig = getStringFromJson(config, KEY_KEY_NAME);
String macroFromConfig = getStringFromJson(config, KEY_MACRO);
String[] keys;
if (keyFromConfig != null && macroFromConfig != null) {
throw new JSONException("Both key and macro can't be set for the same key. key: \"" + keyFromConfig + "\", macro: \"" + macroFromConfig + "\"");
} else if (keyFromConfig != null) {
keys = new String[]{keyFromConfig};
this.macro = false;
} else if (macroFromConfig != null) {
keys = macroFromConfig.split(" ");
this.macro = true;
} else {
throw new JSONException("All keys have to specify either key or macro");
}
for (int i = 0; i < keys.length; i++) {
keys[i] = replaceAlias(extraKeyAliasMap, keys[i]);
}
this.key = TextUtils.join(" ", keys);
String displayFromConfig = getStringFromJson(config, KEY_DISPLAY_NAME);
if (displayFromConfig != null) {
this.display = displayFromConfig;
} else {
this.display = Arrays.stream(keys)
.map(key -> extraKeyDisplayMap.get(key, key))
.collect(Collectors.joining(" "));
}
this.popup = popup;View on GitHub (pinned to 3df69d1da1)
Solutions
- Add either a "key":"..." or "macro":"..." field to the button object.
- Check for field-name typos against ExtraKeyButton.KEY_KEY_NAME and KEY_MACRO constants.
- Remove placeholder/empty objects from the matrix.
Example fix
// before (invalid: no key or macro)
{"display": "Tab"}
// after (key specified)
{"key": "TAB", "display": "Tab"} Defensive patterns
Strategy: validation
Validate before calling
boolean hasKey = config.has(ExtraKeyButton.KEY_KEY_NAME);
boolean hasMacro = config.has(ExtraKeyButton.KEY_MACRO);
if (!hasKey && !hasMacro) {
throw new JSONException("Button must define 'key' or 'macro'");
} Try / catch
try {
new ExtraKeyButton(config, popup, displayMap, aliasMap);
} catch (JSONException e) {
if (e.getMessage() != null && e.getMessage().contains("specify either key or macro")) {
// prompt user to fix the empty/typo'd button
reportConfigError(e.getMessage());
} else throw e;
} Prevention
- Every button object must contain a 'key' or 'macro' field.
- Watch for field-name typos ('keys', 'Key') that silently make a button empty.
- Remove empty placeholder objects from the matrix.
When it happens
Trigger: An extra-keys button object like {} or {"display":"foo"} with no key/macro field; a malformed config where the key name was misspelled (e.g. "keys" instead of "key").
Common situations: Typo in field name ('keys', 'Key', 'MACRO'); empty button object left as a placeholder; display-only object mistakenly used as a button.
Related errors
- Both key and macro can't be set for the same key. key: "%s",
- An key in the extra-key matrix must be a string or an object
- Unsupported TERMUX_APP_PACKAGE_VARIANT "%s"
- Unsupported TERMUX_APP_PACKAGE_MANAGER "%s" with variant "%s
- Unsupported TERMUX_PACKAGE_VARIANT "%s"
AI-assisted analysis of termux/termux-app@3df69d1da1 (2026-08-13).
Data as JSON: /api/errors/c8cb60e8e8eb537b.
Report an issue: GitHub.