{"record":{"id":"8d0c73daee40224a","repo":"termux/termux-app","slug":"failed-to-delete-document-with-id","errorCode":null,"errorMessage":"Failed to delete document with id ","messagePattern":"Failed to delete document with id ","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/com/termux/filepicker/TermuxDocumentsProvider.java","lineNumber":145,"sourceCode":"            if (Document.MIME_TYPE_DIR.equals(mimeType)) {\n                succeeded = newFile.mkdir();\n            } else {\n                succeeded = newFile.createNewFile();\n            }\n            if (!succeeded) {\n                throw new FileNotFoundException(\"Failed to create document with id \" + newFile.getPath());\n            }\n        } catch (IOException e) {\n            throw new FileNotFoundException(\"Failed to create document with id \" + newFile.getPath());\n        }\n        return newFile.getPath();\n    }\n\n    @Override\n    public void deleteDocument(String documentId) throws FileNotFoundException {\n        File file = getFileForDocId(documentId);\n        if (!file.delete()) {\n            throw new FileNotFoundException(\"Failed to delete document with id \" + documentId);\n        }\n    }\n\n    @Override\n    public String getDocumentType(String documentId) throws FileNotFoundException {\n        File file = getFileForDocId(documentId);\n        return getMimeType(file);\n    }\n\n    @Override\n    public Cursor querySearchDocuments(String rootId, String query, String[] projection) throws FileNotFoundException {\n        final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);\n        final File parent = getFileForDocId(rootId);\n\n        // This example implementation searches file names for the query and doesn't rank search\n        // results, so we can stop as soon as we find a sufficient number of matches.  Other\n        // implementations might rank results and use other data about files, rather than the file\n        // name, to produce a match.","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/termux/termux-app/blob/3df69d1da197dd9bd71a3bafd902dffd720576b4/app/src/main/java/com/termux/filepicker/TermuxDocumentsProvider.java#L127-L163","documentation":"Thrown by TermuxDocumentsProvider.deleteDocument when File.delete() returns false, meaning the file/directory could not be removed. Common reasons: the path is a non-empty directory, the file is locked/open, or the process lacks permission. SAF requires deleteDocument to throw FileNotFoundException on failure so the framework reports the deletion as unsuccessful.","triggerScenarios":"Deleting a directory that still contains children (File.delete fails on non-empty dirs); deleting a file held open by another process; read-only filesystem; permission denial.","commonSituations":"Client requests deletion of a populated directory without emptying it first; file locked by an editor or shell; storage mounted read-only.","solutions":["If the document is a directory, recursively delete its contents before calling deleteDocument, or implement recursive delete.","Close any open file descriptors to the target before deletion.","Verify the path is writable and the storage is not read-only.","Check logcat for the underlying reason delete() returned false."],"exampleFix":"// before\npublic void deleteDocument(String documentId) throws FileNotFoundException {\n    File file = getFileForDocId(documentId);\n    if (!file.delete()) {\n        throw new FileNotFoundException(\"Failed to delete document with id \" + documentId);\n    }\n}\n\n// after (recursive delete for directories)\npublic void deleteDocument(String documentId) throws FileNotFoundException {\n    File file = getFileForDocId(documentId);\n    boolean ok = file.isDirectory() ? deleteRecursively(file) : file.delete();\n    if (!ok) {\n        throw new FileNotFoundException(\"Failed to delete document with id \" + documentId);\n    }\n}","handlingStrategy":"validation","validationCode":"File file = new File(documentId);\nif (!file.exists()) {\n    // nothing to delete; treat as success or signal caller\n}\nif (file.isDirectory() && file.list().length > 0) {\n    // must empty first\n    throw new IOException(\"Directory not empty: \" + documentId);\n}","typeGuard":null,"tryCatchPattern":"try {\n    provider.deleteDocument(documentId);\n} catch (FileNotFoundException e) {\n    // document already gone; acceptable in many clients\n    Log.w(TAG, \"Already deleted: \" + documentId);\n}","preventionTips":["Empty directories before deletion, or implement recursive delete.","Close open file descriptors to the target before deleting.","Treat FileNotFoundException on delete as 'already gone' when idempotency is acceptable."],"tags":["documents-provider","saf","filesystem","termux"],"backgroundTag":null,"analyzedSha":"3df69d1da197dd9bd71a3bafd902dffd720576b4","analyzedAt":"2026-08-13T22:46:28.294Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}