{"record":{"id":"837ebcda10856972","repo":"TeamNewPipe/NewPipe","slug":"json-doesn-t-contain-tabs-array","errorCode":null,"errorMessage":"JSON doesn't contain \"tabs\" array","messagePattern":"JSON doesn't contain \"tabs\" array","errorType":"exception","errorClass":"InvalidJsonException","httpStatus":null,"severity":"warning","filePath":"app/src/main/java/org/schabi/newpipe/settings/tabs/TabsJsonHelper.java","lineNumber":52,"sourceCode":"     * {@link #getDefaultTabs fallback list} will be returned.\n     * <p>\n     * Tabs with invalid ids (i.e. not in the {@link Tab.Type} enum) will be ignored.\n     *\n     * @param tabsJson a JSON string got from {@link #getJsonToSave(List)}.\n     * @return a list of {@link Tab tabs}.\n     * @throws InvalidJsonException if the JSON string is not valid\n     */\n    public static List<Tab> getTabsFromJson(@Nullable final String tabsJson)\n            throws InvalidJsonException {\n        if (tabsJson == null || tabsJson.isEmpty()) {\n            return getDefaultTabs();\n        }\n\n        try {\n            final JsonObject outerJsonObject = JsonParser.object().from(tabsJson);\n\n            if (!outerJsonObject.has(JSON_TABS_ARRAY_KEY)) {\n                throw new InvalidJsonException(\"JSON doesn't contain \\\"\" + JSON_TABS_ARRAY_KEY\n                        + \"\\\" array\");\n            }\n\n            final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY, null);\n\n            final var returnTabs = tabsArray.streamAsJsonObjects()\n                    .map(Tab::from)\n                    .filter(Objects::nonNull)\n                    .collect(Collectors.toUnmodifiableList());\n\n            return returnTabs.isEmpty() ? getDefaultTabs() : returnTabs;\n        } catch (final JsonParserException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    /**\n     * Get a JSON representation from a list of tabs.","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/TeamNewPipe/NewPipe/blob/9e8be091560a69f35d44bd252eb00bc7911c977b/app/src/main/java/org/schabi/newpipe/settings/tabs/TabsJsonHelper.java#L34-L70","documentation":"Thrown by TabsJsonHelper.getTabsFromJson when the parsed top-level JSON object does not contain the \"tabs\" key (JSON_TABS_ARRAY_KEY). The method expects an object with a tabs array; absence of that key is treated as invalid tab configuration and raises an InvalidJsonException. Note: a null/empty input string returns default tabs instead, so this only fires for a non-empty JSON lacking the key.","triggerScenarios":"getTabsFromJson is called with a non-empty JSON string whose top-level object has no \"tabs\" field. JsonParser.object().from succeeds (valid JSON) but outerJsonObject.has(\"tabs\") is false.","commonSituations":"Corrupted or hand-edited tab settings JSON where the \"tabs\" key was removed or renamed, a migration/schema change that left an outdated JSON shape, or a partial write that saved a different object structure. The stored tabs preference (in SharedPreferences) got into an inconsistent state.","solutions":["Catch InvalidJsonException and fall back to getDefaultTabs() so the app still launches with sane defaults, then let the user reconfigure.","Clear/reset the tabs preference to restore the default tabs JSON.","Validate the JSON structure (presence of the \"tabs\" key) before persisting it, and write atomically to avoid truncated/corrupt saves.","Add a migration step that upgrades older JSON shapes to the current {\"tabs\":[...]} structure."],"exampleFix":"// before\ntry {\n    return TabsJsonHelper.getTabsFromJson(json);\n} catch (final InvalidJsonException e) {\n    throw e;\n}\n// after\ntry {\n    return TabsJsonHelper.getTabsFromJson(json);\n} catch (final InvalidJsonException e) {\n    return TabsJsonHelper.getDefaultTabs();\n}","handlingStrategy":"try-catch","validationCode":"final JsonObject obj = JsonParser.object().from(tabsJson);\nif (!obj.has(\"tabs\")) {\n    // return default tabs instead of throwing\n}","typeGuard":null,"tryCatchPattern":"try {\n    return TabsJsonHelper.getTabsFromJson(tabsJson);\n} catch (final InvalidJsonException e) {\n    return TabsJsonHelper.getDefaultTabs();\n}","preventionTips":["Validate the JSON shape (has \"tabs\" key) before persisting it.","Write tab preferences atomically to avoid truncated/corrupt saves.","Catch InvalidJsonException and fall back to default tabs so the app always launches.","Add a migration for older JSON shapes when the schema changes."],"tags":["settings","json","parsing","tabs","configuration"],"backgroundTag":null,"analyzedSha":"9e8be091560a69f35d44bd252eb00bc7911c977b","analyzedAt":"2026-08-14T00:11:33.519Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}