{"record":{"id":"ed976f0f2ff43038","repo":"MuntashirAkon/AppManager","slug":"empty-profile-path","errorCode":null,"errorMessage":"Empty profile path","messagePattern":"Empty profile path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/profiles/struct/BaseProfile.java","lineNumber":38,"sourceCode":"import java.lang.annotation.RetentionPolicy;\nimport java.util.Objects;\n\nimport io.github.muntashirakon.AppManager.history.IJsonSerializer;\nimport io.github.muntashirakon.AppManager.history.JsonDeserializer;\nimport io.github.muntashirakon.AppManager.profiles.ProfileLogger;\nimport io.github.muntashirakon.AppManager.profiles.ProfileManager;\nimport io.github.muntashirakon.AppManager.progress.ProgressHandler;\nimport io.github.muntashirakon.AppManager.utils.JSONUtils;\nimport io.github.muntashirakon.io.Path;\nimport io.github.muntashirakon.io.Paths;\nimport io.github.muntashirakon.util.LocalizedString;\n\npublic abstract class BaseProfile implements LocalizedString, IJsonSerializer {\n    @Contract(\"null -> fail\")\n    @NonNull\n    public static BaseProfile fromPath(@Nullable Path profilePath) throws IOException, JSONException {\n        if (profilePath == null) {\n            throw new IOException(\"Empty profile path\");\n        }\n        String profileStr = profilePath.getContentAsString();\n        JSONObject profileObj = new JSONObject(profileStr);\n        return BaseProfile.DESERIALIZER.deserialize(profileObj);\n    }\n\n    @NonNull\n    public static BaseProfile newProfile(@NonNull String newProfileName, int type, @Nullable BaseProfile source) {\n        String profileId = ProfileManager.getProfileIdCompat(newProfileName);\n        // TODO: 17/9/23 TODO: Remove these once we migrated to UUID based profile ID\n        // BEGIN legacy: For legacy profile, the generated ID can be the same as an existing profile\n        Path profilesDir = ProfileManager.getProfilesDir();\n        Path profilePath = Paths.build(profilesDir, profileId + PROFILE_EXT);\n        String profileName = newProfileName;\n        int i = 1;\n        while (profilePath != null && profilePath.exists()) {\n            // Try another name\n            profileName = newProfileName + \" (\" + i + \")\";","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/profiles/struct/BaseProfile.java#L20-L56","documentation":"BaseProfile.fromPath is annotated @Contract(\"null -> fail\"): it requires a non-null Path to a profile JSON file. Passing null gives it nothing to read, so it throws IOException('Empty profile path') before attempting to deserialize.","triggerScenarios":"Calling BaseProfile.fromPath(null), typically when a profile file path lookup failed upstream and the null result was passed through unguarded.","commonSituations":"Profile name typo causing a directory-listing lookup to return null; calling the API before the profiles directory exists; migrating code that previously used names instead of Path objects.","solutions":["Check that the profile Path exists and is non-null before calling fromPath","Fix the upstream lookup that produced the null Path (wrong profile name or missing profiles directory)","Catch IOException around fromPath if null paths are legitimately possible in your flow"],"exampleFix":"// before\nBaseProfile profile = BaseProfile.fromPath(lookupProfile(name));\n// after\nPath path = lookupProfile(name);\nif (path == null) {\n    throw new FileNotFoundException(\"Profile not found: \" + name);\n}\nBaseProfile profile = BaseProfile.fromPath(path);","handlingStrategy":"validation","validationCode":"if (profilePath == null || !Files.exists(profilePath)) {\n    throw new FileNotFoundException(\"Profile not found: \" + profilePath);\n}","typeGuard":"@Nullable Path resolveProfile(String name) {\n    Path p = profilesDir.resolve(name + PMF_EXT);\n    return Files.exists(p) ? p : null;\n}\n// caller: only call fromPath when resolveProfile != null","tryCatchPattern":"try {\n    BaseProfile profile = BaseProfile.fromPath(path);\n} catch (IOException | JSONException e) {\n    showError(\"Cannot load profile: \" + e.getMessage());\n}","preventionTips":["Never pass nullable lookup results straight into fromPath","Confirm the profiles directory exists before listing/loading","Use null-check or Optional around profile path lookups"],"tags":["profiles","null","io","android"],"backgroundTag":"null-argument","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}