{"record":{"id":"999622b63e286a6e","repo":"libgdx/libgdx","slug":"cannot-delete-an-internal-file","errorCode":null,"errorMessage":"Cannot delete an internal file: ","messagePattern":"Cannot delete an internal file: ","errorType":"exception","errorClass":"GdxRuntimeException","httpStatus":null,"severity":"error","filePath":"backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtFileHandle.java","lineNumber":365,"sourceCode":"\tpublic FileHandle sibling (String name) {\n\t\treturn parent().child(fixSlashes(name));\n\t}\n\n\t/** @throws GdxRuntimeException if this file handle is a {@link FileType#Classpath} or {@link FileType#Internal} file. */\n\tpublic void mkdirs () {\n\t\tthrow new GdxRuntimeException(\"Cannot mkdirs with an internal file: \" + file);\n\t}\n\n\t/** Returns true if the file exists. On Android, a {@link FileType#Classpath} or {@link FileType#Internal} handle to a\n\t * directory will always return false. */\n\tpublic boolean exists () {\n\t\treturn preloader.contains(file);\n\t}\n\n\t/** Deletes this file or empty directory and returns success. Will not delete a directory that has children.\n\t * @throws GdxRuntimeException if this file handle is a {@link FileType#Classpath} or {@link FileType#Internal} file. */\n\tpublic boolean delete () {\n\t\tthrow new GdxRuntimeException(\"Cannot delete an internal file: \" + file);\n\t}\n\n\t/** Deletes this file or directory and all children, recursively.\n\t * @throws GdxRuntimeException if this file handle is a {@link FileType#Classpath} or {@link FileType#Internal} file. */\n\tpublic boolean deleteDirectory () {\n\t\tthrow new GdxRuntimeException(\"Cannot delete an internal file: \" + file);\n\t}\n\n\t/** Copies this file or directory to the specified file or directory. If this handle is a file, then 1) if the destination is a\n\t * file, it is overwritten, or 2) if the destination is a directory, this file is copied into it, or 3) if the destination\n\t * doesn't exist, {@link #mkdirs()} is called on the destination's parent and this file is copied into it with a new name. If\n\t * this handle is a directory, then 1) if the destination is a file, GdxRuntimeException is thrown, or 2) if the destination is\n\t * a directory, this directory is copied into it recursively, overwriting existing files, or 3) if the destination doesn't\n\t * exist, {@link #mkdirs()} is called on the destination and this directory is copied into it recursively.\n\t * @throws GdxRuntimeException if the destination file handle is a {@link FileType#Classpath} or {@link FileType#Internal}\n\t *            file, or copying failed. */\n\tpublic void copyTo (FileHandle dest) {\n\t\tthrow new GdxRuntimeException(\"Cannot copy to an internal file: \" + dest);","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/libgdx/libgdx/blob/97f40861878058087be0685ca167ddfde132134b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtFileHandle.java#L347-L383","documentation":"GwtFileHandle.delete() unconditionally throws 'Cannot delete an internal file: <path>'. Preloaded assets are baked into the application bundle and immutable from JavaScript; the GWT backend exposes no deletion. The message text says 'internal file' because only Internal/Classpath handles can exist in this backend.","triggerScenarios":"Calling delete() on a FileHandle under GwtApplication — typically save-management code that removes old save files, or cleanup code that deletes temporary files after use.","commonSituations":"Ported save-slot management (delete save X) that uses file deletion on desktop; cache-clearing code; shared utilities that tidy up temporary assets.","solutions":["On the web build, 'deletion' means removing a key from Preferences/localStorage — implement it in a platform-specific save manager.","Branch on Gdx.app.getType() == ApplicationType.WebGL before any delete() call in shared code.","Audit ported code for delete()/deleteDirectory() usage when adding the GWT target."],"exampleFix":"// before\nGdx.files.local(\"saves/slot1.json\").delete(); // throws on GWT\n\n// after\nif (Gdx.app.getType() == ApplicationType.WebGL) {\n    Gdx.app.getPreferences(\"saves\").remove(\"slot1\").flush();\n} else {\n    Gdx.files.local(\"saves/slot1.json\").delete();\n}","handlingStrategy":"validation","validationCode":"// 'delete' on web means removing a storage key\nif (Gdx.app.getType() == ApplicationType.WebGL) {\n    Gdx.app.getPreferences(\"saves\").remove(\"slot1\").flush();\n} else {\n    Gdx.files.local(\"saves/slot1.json\").delete();\n}","typeGuard":"static boolean canDeleteFiles () {\n    return Gdx.app.getType() != ApplicationType.WebGL;\n}","tryCatchPattern":null,"preventionTips":["Model deletable entities as keys, not files, in shared code.","Audit save-management features (delete slot, reset game) when porting to GWT.","delete() and deleteDirectory() both throw on GWT — treat them as one audit item."],"tags":["gwt","libgdx","filehandle","delete","read-only","unsupported-operation"],"backgroundTag":null,"analyzedSha":"97f40861878058087be0685ca167ddfde132134b","analyzedAt":"2026-08-14T10:52:53.492Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}