{"record":{"id":"1ad92714a0a14fe6","repo":"termux/termux-app","slug":"an-key-in-the-extra-key-matrix-must-be-a-string-or","errorCode":null,"errorMessage":"An key in the extra-key matrix must be a string or an object","messagePattern":"An key in the extra-key matrix must be a string or an object","errorType":"validation","errorClass":"JSONException","httpStatus":null,"severity":"error","filePath":"termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeysInfo.java","lineNumber":188,"sourceCode":"            }\n        }\n\n        return buttons;\n    }\n\n    /**\n     * Convert \"value\" -> {\"key\": \"value\"}. Required by\n     * {@link ExtraKeyButton#ExtraKeyButton(JSONObject, ExtraKeyButton, ExtraKeysConstants.ExtraKeyDisplayMap, ExtraKeysConstants.ExtraKeyDisplayMap)}.\n     */\n    private static JSONObject normalizeKeyConfig(Object key) throws JSONException {\n        JSONObject jobject;\n        if (key instanceof String) {\n            jobject = new JSONObject();\n            jobject.put(ExtraKeyButton.KEY_KEY_NAME, key);\n        } else if (key instanceof JSONObject) {\n            jobject = (JSONObject) key;\n        } else {\n            throw new JSONException(\"An key in the extra-key matrix must be a string or an object\");\n        }\n        return jobject;\n    }\n\n    public ExtraKeyButton[][] getMatrix() {\n        return mButtons;\n    }\n\n    @NonNull\n    public static ExtraKeysConstants.ExtraKeyDisplayMap getCharDisplayMapForStyle(String style) {\n        switch (style) {\n            case \"arrows-only\":\n                return EXTRA_KEY_DISPLAY_MAPS.ARROWS_ONLY_CHAR_DISPLAY;\n            case \"arrows-all\":\n                return EXTRA_KEY_DISPLAY_MAPS.LOTS_OF_ARROWS_CHAR_DISPLAY;\n            case \"all\":\n                return EXTRA_KEY_DISPLAY_MAPS.FULL_ISO_CHAR_DISPLAY;\n            case \"none\":","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/termux/termux-app/blob/3df69d1da197dd9bd71a3bafd902dffd720576b4/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeysInfo.java#L170-L206","documentation":"Thrown by ExtraKeysInfo.normalizeKeyConfig when an element in the extra-key matrix is neither a JSON String nor a JSONObject. The matrix is expected to be an array of arrays where each cell is a plain string (auto-wrapped to {\"key\": value}) or an object. Any other JSON type (number, boolean, array, null) is rejected.","triggerScenarios":"The extra-keys JSON matrix contains a numeric literal (e.g. 1), a boolean (true), null, or a nested array where a button cell is expected: [[\"CTRL\", 1], ...].","commonSituations":"Hand-editing the matrix and putting a number/boolean instead of a key name; malformed JSON where a key name lost its quotes; templating bug inserting a non-string token.","solutions":["Ensure every cell in the matrix is either a quoted string or a JSON object.","Quote key names that look numeric or boolean (e.g. use \"1\" not 1).","Run the JSON through a validator and fix type mismatches in the matrix."],"exampleFix":"// before (invalid: numeric cell)\n[[\"CTRL\", 1], [\"ALT\", \"TAB\"]]\n\n// after (string cell)\n[[\"CTRL\", \"1\"], [\"ALT\", \"TAB\"]]","handlingStrategy":"type-guard","validationCode":"if (!(key instanceof String) && !(key instanceof JSONObject)) {\n    throw new JSONException(\"Matrix cell must be a string or object, got: \"\n        + (key == null ? \"null\" : key.getClass().getSimpleName()));\n}","typeGuard":"private static boolean isValidKeyCell(Object key) {\n    return key instanceof String || key instanceof JSONObject;\n}","tryCatchPattern":"try {\n    normalizeKeyConfig(cell);\n} catch (JSONException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"must be a string or an object\")) {\n        // coerce/quote the value or drop the cell\n        cell = String.valueOf(cell);\n    } else throw e;\n}","preventionTips":["Ensure every matrix cell is a quoted string or a JSON object.","Quote numerically-named keys rather than using raw numbers.","Validate the matrix with a schema that restricts cell types."],"tags":["extra-keys","json","type-validation","configuration","termux"],"backgroundTag":null,"analyzedSha":"3df69d1da197dd9bd71a3bafd902dffd720576b4","analyzedAt":"2026-08-13T22:46:28.294Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}