{"record":{"id":"1378d1ee2d70f577","repo":"asLody/VirtualApp","slug":"couldn-t-append","errorCode":null,"errorMessage":"Couldn't append ","messagePattern":"Couldn't append ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/AtomicFile.java","lineNumber":196,"sourceCode":"                    System.arraycopy(data, 0, newData, 0, pos);\n                    data = newData;\n                }\n            }\n        } finally {\n            stream.close();\n        }\n    }\n\n    /**\n     * @deprecated This is not safe.\n     */\n    public void truncate() throws IOException {\n        try {\n            FileOutputStream fos = new FileOutputStream(mBaseName);\n            fos.getFD().sync();\n            fos.close();\n        } catch (FileNotFoundException e) {\n            throw new IOException(\"Couldn't append \" + mBaseName);\n        } catch (IOException e) {\n        }\n    }\n\n    /**\n     * @deprecated This is not safe.\n     */\n    @Deprecated public FileOutputStream openAppend() throws IOException {\n        try {\n            return new FileOutputStream(mBaseName, true);\n        } catch (FileNotFoundException e) {\n            throw new IOException(\"Couldn't append \" + mBaseName);\n        }\n    }\n\n    static boolean sync(FileOutputStream stream) {\n        try {\n            if (stream != null) {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/AtomicFile.java#L178-L214","documentation":"AtomicFile.truncate() opens the base file for output to zero it out. On FileNotFoundException it throws IOException 'Couldn't append <path>' (message wording is misleading — this is an open/create failure, not append). The generic IOException from sync/close is swallowed.","triggerScenarios":"Calling truncate() when mBaseName cannot be opened for writing: parent directory missing, storage read-only, or the file path is not writable by the app uid.","commonSituations":"Truncating before any startWrite ever created the file/directory; sdcard unmounted; path moved after refactor.","solutions":["Ensure the file's parent directory and file exist (call startWrite/newFile once) before truncate","Check write permission/storage state for the base path","Wrap truncate in try-catch and recreate the AtomicFile from a valid directory"],"exampleFix":"// before\natomicFile.truncate(); // FileNotFoundException if file/dir missing\n// after\nFile parent = base.getParentFile();\nif (!parent.exists()) parent.mkdirs();\nif (!base.exists()) base.createNewFile();\natomicFile.truncate();","handlingStrategy":"validation","validationCode":"File base = ...;\nif (!base.exists()) {\n    base.getParentFile().mkdirs();\n    base.createNewFile();\n}","typeGuard":null,"tryCatchPattern":"try {\n    atomicFile.truncate();\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Couldn't append\")) {\n        // file missing: recreate via startWrite before truncating\n    }\n}","preventionTips":["Never truncate an AtomicFile before its first startWrite","Avoid the deprecated truncate/openAppend APIs","Check base path existence and writability first"],"tags":["android","io","file-not-found","atomic-file"],"backgroundTag":"file-not-found","analyzedSha":"666fefcb5d3f39cc944001c3457c38ffd6544c87","analyzedAt":"2026-09-09T11:09:01.694Z","contentChangedAt":"2026-09-09T11:09:01.694Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}