{"record":{"id":"2a222fd43a415ff2","repo":"MuntashirAkon/AppManager","slug":"content-provider-has-crashed-rulesimporter","errorCode":null,"errorMessage":"Content provider has crashed.","messagePattern":"Content provider has crashed\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/rules/RulesImporter.java","lineNumber":61,"sourceCode":"    private final int[] mUserIds;\n\n    public RulesImporter(@NonNull List<RuleType> typesToImport, @NonNull int[] userIds) {\n        if (userIds.length == 0) {\n            throw new IllegalArgumentException(\"Input must contain one or more user handles\");\n        }\n        // Init CBs\n        //noinspection unchecked\n        mComponentsBlockers = new HashMap[userIds.length];\n        for (int i = 0; i < userIds.length; ++i) {\n            mComponentsBlockers[i] = new HashMap<>();\n        }\n        mTypesToImport = typesToImport;\n        mUserIds = userIds;\n    }\n\n    public void addRulesFromUri(Uri uri) throws IOException {\n        try (InputStream inputStream = ContextUtils.getContext().getContentResolver().openInputStream(uri)) {\n            if (inputStream == null) throw new IOException(\"Content provider has crashed.\");\n            try (BufferedReader TSVFile = new BufferedReader(new InputStreamReader(inputStream))) {\n                String dataRow;\n                while ((dataRow = TSVFile.readLine()) != null) {\n                    RuleEntry entry = RuleEntry.unflattenFromString(null, dataRow, true);\n                    // Parse complete, now add the row to CB\n                    for (int i = 0; i < mUserIds.length; ++i) {\n                        if (mComponentsBlockers[i].get(entry.packageName) == null) {\n                            // Get a read-only instance, commit will be called manually\n                            mComponentsBlockers[i].put(entry.packageName, ComponentsBlocker.getInstance(entry.packageName, mUserIds[i]));\n                        }\n                        if (mTypesToImport.contains(entry.type)) {\n                            //noinspection ConstantConditions Returned ComponentsBlocker will never be null here\n                            mComponentsBlockers[i].get(entry.packageName).addEntry(entry);\n                        }\n                    }\n                }\n            }\n        }","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/rules/RulesImporter.java#L43-L79","documentation":"RulesImporter.addRulesFromUri opens an InputStream via ContentResolver.openInputStream(); per the ContentResolver contract this can return null when the provider behind the Uri fails. The importer throws IOException('Content provider has crashed.') in that case because there is no stream to parse TSV rules from.","triggerScenarios":"Calling addRulesFromUri(uri) where openInputStream returns null: the source document was deleted after picking, the provider process crashed, or the Uri lacks read grants.","commonSituations":"Re-importing from a backup Uri whose file was moved/deleted; reading from a documents provider that unmounted (SD card removed); persisted URI permissions revoked.","solutions":["Verify the source file still exists and takePersistableUriPermission after SAF picking","Re-select the backup file via ACTION_OPEN_DOCUMENT to get a fresh readable Uri","Catch the IOException and prompt the user to re-pick the import source","Check persisted URI permissions with contentResolver.getPersistedUriPermissions()"],"exampleFix":"// before\nimporter.addRulesFromUri(savedUri);\n// after\ntry {\n    importer.addRulesFromUri(savedUri);\n} catch (IOException e) {\n    launcher.openDocument(); // re-pick the backup file\n}","handlingStrategy":"try-catch","validationCode":"List<UriPermission> perms = context.getContentResolver().getPersistedUriPermissions();\nboolean readable = perms.stream().anyMatch(p -> p.isReadPermission() && p.getUri().equals(uri));\nif (!readable) throw new IOException(\"No read access to import source: \" + uri);","typeGuard":null,"tryCatchPattern":"try {\n    importer.addRulesFromUri(uri);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"Content provider has crashed\")) {\n        promptRepickSource();\n    } else throw e;\n}","preventionTips":["Call takePersistableUriPermission after ACTION_OPEN_DOCUMENT","Verify the source file exists before each import","Re-pick the document rather than reusing stale Uris across sessions"],"tags":["android","content-provider","io","import"],"backgroundTag":"file-read-failed","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"}