MuntashirAkon/AppManager · error
ClosedChannelException
Error message
ClosedChannelException
What it means
OpenFile wraps a native file descriptor with synchronized operations (lseek, size, ftruncate, sync, etc.). Internal ensureOpen() checks that fd is still non-null; once close() has been called, fd is nulled and any subsequent operation throws ClosedChannelException, mirroring java.nio channels closed-state semantics.
Source
Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/OpenFile.java:51
private ByteBuffer buf;
private StructStat st;
private ByteBuffer getBuf() {
if (buf == null)
buf = ByteBuffer.allocateDirect(FileSystemService.PIPE_CAPACITY);
buf.clear();
return buf;
}
private StructStat getStat() throws ErrnoException {
if (st == null)
st = Os.fstat(fd);
return st;
}
private void ensureOpen() throws ClosedChannelException {
if (fd == null)
throw new ClosedChannelException();
}
@Override
synchronized public void close() {
if (fd != null) {
try {
Os.close(fd);
} catch (ErrnoException ignored) {
}
fd = null;
}
if (read != null) {
try {
Os.close(read);
} catch (ErrnoException ignored) {
}
read = null;
}View on GitHub (pinned to 0152f468fc)
Solutions
- Catch ClosedChannelException and reopen the file via FileSystemManager before retrying the operation
- Guard usage so no operation occurs after close (lifecycle management, single owner thread)
- Synchronize usage with close (the methods are synchronized; ensure the same monitor/lifecycle governs both)
Example fix
// before
openFile.close();
openFile.size(); // ClosedChannelException
// after
openFile.close();
if (!openFileClosed) { // or reopen instead
OpenFile reopened = fm.openFile(path, "r");
long sz = reopened.size();
} Defensive patterns
Strategy: try-catch
Try / catch
try { long sz = openFile.size(); } catch (ClosedChannelException e) { openFile = fm.openFile(path, mode); sz = openFile.size(); } Prevention
- Treat OpenFile as single-owner: close once, never use afterwards
- Use the file's own streams and close them before closing the file
- Avoid sharing OpenFile across threads without clear close ownership
When it happens
Trigger: Calling lseek(), size(), ftruncate(), sync() (or anything else routed through ensureOpen) after close() on the same OpenFile; concurrent close from another thread while an operation is in flight; using an OpenFile returned from a remote manager whose file was closed remotely.
Common situations: try-with-resources or explicit close followed by lingering references still used; races between a close in a cleanup path and a read/write worker; reopening expectations after process restart without reacquiring the OpenFile.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/80e59679e202d5b5.
Report an issue: GitHub.