libgdx/libgdx · error · GdxRuntimeException
Cannot write to files in GWT backend
Error message
Cannot write to files in GWT backend
What it means
GwtFileHandle.write(boolean append) always throws: the GWT backend is strictly read-only for files because assets live in the preloaded, in-memory bundle and browsers give JavaScript no arbitrary file-write capability. Every write-family method in this class (write, write(InputStream,...), writer, writeString, writeBytes) is overridden to throw the same message.
Source
Thrown at backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtFileHandle.java:231
}
}
return position - offset;
}
public ByteBuffer map () {
throw new GdxRuntimeException("Cannot map files in GWT backend");
}
public ByteBuffer map (FileChannel.MapMode mode) {
throw new GdxRuntimeException("Cannot map files in GWT backend");
}
/** Returns a stream for writing to this file. Parent directories will be created if necessary.
* @param append If false, this file will be overwritten if it exists, otherwise it will be appended.
* @throws GdxRuntimeException if this file handle represents a directory, if it is a {@link FileType#Classpath} or
* {@link FileType#Internal} file, or if it could not be written. */
public OutputStream write (boolean append) {
throw new GdxRuntimeException("Cannot write to files in GWT backend");
}
/** Reads the remaining bytes from the specified stream and writes them to this file. The stream is closed. Parent directories
* will be created if necessary.
* @param append If false, this file will be overwritten if it exists, otherwise it will be appended.
* @throws GdxRuntimeException if this file handle represents a directory, if it is a {@link FileType#Classpath} or
* {@link FileType#Internal} file, or if it could not be written. */
public void write (InputStream input, boolean append) {
throw new GdxRuntimeException("Cannot write to files in GWT backend");
}
/** Returns a writer for writing to this file using the default charset. Parent directories will be created if necessary.
* @param append If false, this file will be overwritten if it exists, otherwise it will be appended.
* @throws GdxRuntimeException if this file handle represents a directory, if it is a {@link FileType#Classpath} or
* {@link FileType#Internal} file, or if it could not be written. */
public Writer writer (boolean append) {
return writer(append, null);
}View on GitHub (pinned to 97f4086187)
Solutions
- Persist web-build state with Preferences (Gdx.app.getPreferences) or HTML5 local storage instead of FileHandle writes.
- Branch on Gdx.app.getType() == ApplicationType.WebGL and route all persistence through a platform-specific interface (web: Preferences/localStorage; desktop: files).
- For downloads (screenshots, exported saves), use browser APIs (e.g. a GWT-native anchor download) rather than the filesystem.
- Audit shared code for write()/writer()/writeString()/writeBytes()/copyTo/moveTo calls before adding the GWT target.
Example fix
// before
Gdx.files.local("save.json").writeString(json, false); // throws on GWT
// after
if (Gdx.app.getType() == ApplicationType.WebGL) {
Gdx.app.getPreferences("save").putString("json", json).flush();
} else {
Gdx.files.local("save.json").writeString(json, false);
} Defensive patterns
Strategy: validation
Validate before calling
// all writes must be routed away from FileHandle on GWT
if (Gdx.app.getType() == ApplicationType.WebGL) {
Gdx.app.getPreferences("data").putString("key", value).flush();
} else {
fh.writeString(value, false);
} Type guard
static boolean isFilesystemWritable () {
return Gdx.app.getType() != ApplicationType.WebGL;
} Prevention
- Introduce a Persistence interface at project start so the web implementation never touches FileHandle writes.
- Audit shared modules for write(/writer(/writeString(/writeBytes( calls before adding the GWT target.
- Use Gdx.app.log for logs instead of file-based logging in shared code.
When it happens
Trigger: Calling write(append) on a FileHandle in the GWT backend — directly, or via shared code such as Preferences serializers, level editors, screenshot savers, or libraries that persist data with Gdx.files.local(...).write(...).
Common situations: Porting a desktop game that saves state with FileHandle.write; JSON/XML libraries that serialize to a FileHandle; screenshot or replay features that dump files; code assuming LocalStorage-like file semantics exist.
Related errors
- Cannot delete an internal file:
- Cannot copy to an internal file:
- Cannot move an internal file:
- FileType '
- file() not supported in GWT backend
AI-assisted analysis of libgdx/libgdx@97f4086187 (2026-08-14).
Data as JSON: /api/errors/b661ce90a9ccbc3c.
Report an issue: GitHub.