MuntashirAkon/AppManager · error · ErrnoException
EBADF
EBADF
Error message
Supplied path is not a Linux path.
What it means
Paths.chmod wraps ExtendedFile.setMode and requires the Path to be backed by a real Linux (ext4/FUSE) file via path.getFile(). When the Path is not Linux-backed (e.g. a SAF/ContentProvider document or virtual filesystem node), getFile() returns null and an ErrnoException with EBADF is thrown.
Source
Thrown at app/src/main/java/io/github/muntashirakon/io/Paths.java:557
// Other types of files aren't supported
return 0;
}
long length = 0;
Path[] files = root.listFiles();
for (Path file : files) {
if (ThreadUtils.isInterrupted()) {
// Size could be too long
return length;
}
length += size(file);
}
return length;
}
public static void chmod(@NonNull Path path, int mode) throws ErrnoException {
ExtendedFile file = path.getFile();
if (file == null) {
throw new ErrnoException("Supplied path is not a Linux path.", OsConstants.EBADF);
}
file.setMode(mode);
}
public static void chown(@NonNull Path path, int uid, int gid) throws ErrnoException {
ExtendedFile file = path.getFile();
if (file == null) {
throw new ErrnoException("Supplied path is not a Linux path.", OsConstants.EBADF);
}
file.setUidGid(uid, gid);
}
/**
* Set owner and mode of given path.
*
* @param mode to apply through {@code chmod}
* @param uid to apply through {@code chown}, or -1 to leave unchanged
* @param gid to apply through {@code chown}, or -1 to leave unchangedView on GitHub (pinned to 0152f468fc)
Solutions
- Verify the path is Linux-backed (path.getFile() != null) before calling chmod.
- Restrict permission changes to files under real filesystem locations (e.g. app-specific or /storage paths), not content:// documents.
- For SAF documents, skip chmod or use the documents-contract APIs that support flags instead.
- Catch the ErrnoException with code EBADF and surface a clear 'operation not supported on this path type' message.
Example fix
// before
Paths.chmod(path, mode);
// after
ExtendedFile f = path.getFile();
if (f == null) throw new UnsupportedOperationException("Not a Linux path: " + path);
Paths.chmod(path, mode); Defensive patterns
Strategy: type-guard
Validate before calling
boolean canChmod = path.getFile() != null;
Type guard
static boolean isLinuxPath(Path p) { return p != null && p.getFile() != null; } Try / catch
try {
Paths.chmod(path, mode);
} catch (ErrnoException e) {
if (e.code == OsConstants.EBADF) {
// not a Linux path: skip or warn
} else throw e;
} Prevention
- Only apply Unix permission operations to Linux-backed paths.
- Treat SAF/content:// paths as permission-opaque and handle them with provider APIs.
- Centralize permission changes behind a helper that checks getFile() first.
When it happens
Trigger: Calling Paths.chmod(path, mode) (directly or via Path.setPermissions) on a Path whose underlying file is a SAF document, a content:// Uri, or any non-ExtendedFile backing where Path.getFile() returns null.
Common situations: Trying to set permissions on a file picked through the Storage Access Framework or on a virtual/mounted node; code assuming all Paths are filesystem-backed after migrating from java.io.File.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Could not delete the selected backups
- Could not create package staging directory
- Could not create directory ${dataSourceFile}
- + path + is inaccessible.
- Warning: chown failed: %s\n
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/bcc93f0582e22baa.
Report an issue: GitHub.