MuntashirAkon/AppManager · error · ErrnoException
ENOSYS
ENOSYS
Error message
splice
What it means
FileUtils.splice() invokes Os.splice() reflectively (required for API 28+). If the reflective lookup of the method or its invocation fails with ReflectiveOperationException, the method throws ErrnoException("splice", ENOSYS) — 'function not implemented'. This translates a reflection/environment problem into an errno so callers can fall back to a non-splice path.
Source
Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/FileUtils.java:154
}
@RequiresApi(api = 28)
static long splice(
FileDescriptor fdIn, Int64Ref offIn,
FileDescriptor fdOut, Int64Ref offOut,
long len, int flags) throws ErrnoException {
try {
if (splice == null) {
splice = Os.class.getMethod("splice",
FileDescriptor.class, Int64Ref.class,
FileDescriptor.class, Int64Ref.class,
long.class, int.class);
}
return (long) splice.invoke(null, fdIn, offIn, fdOut, offOut, len, flags);
} catch (InvocationTargetException e) {
throw (ErrnoException) e.getTargetException();
} catch (ReflectiveOperationException e) {
throw new ErrnoException("splice", ENOSYS);
}
}
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
static long sendfile(
FileDescriptor outFd, FileDescriptor inFd,
MutableLong inOffset, long byteCount) throws ErrnoException {
if (Build.VERSION.SDK_INT >= 28) {
Int64Ref off = inOffset == null ? null : new Int64Ref(inOffset.value);
long result = Os.sendfile(outFd, inFd, off, byteCount);
if (off != null)
inOffset.value = off.value;
return result;
} else {
try {
if (os == null) {
os = Class.forName("libcore.io.Libcore").getField("os").get(null);View on GitHub (pinned to 0152f468fc)
Solutions
- Update the OS/ROM or test on a device with API >= 28 and an unmodified framework
- Catch ErrnoException with errno == ENOSYS and fall back to the read/write loop path (the library's FORCE_NO_SPLICE fallback pattern)
- Set the library's no-splice option (e.g. FORCE_NO_SPLICE) to bypass splice entirely
Example fix
// before
long n = FileUtils.splice(fdIn, offIn, fdOut, offOut, len, 0);
// after
try {
n = FileUtils.splice(fdIn, offIn, fdOut, offOut, len, 0);
} catch (ErrnoException e) {
if (e.errno == OsConstants.ENOSYS) {
n = fallbackCopy(fdIn, offIn, fdOut, offOut, len); // manual read/write loop
} else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
if (Build.VERSION.SDK_INT < 28) { /* skip splice path */ } Try / catch
try { long n = FileUtils.splice(fdIn, offIn, fdOut, offOut, len, 0); } catch (ErrnoException e) { if (e.errno == OsConstants.ENOSYS) { /* manual copy fallback */ } else throw e; } Prevention
- Prefer the library's high-level APIs that already implement the FORCE_NO_SPLICE fallback
- Test on real production devices/ROMs, not only stock emulators
- Keep the library updated for hidden-API restriction workarounds
When it happens
Trigger: Calling splice-based I/O (e.g. OpenFile.pread/read on API >= 28 paths that use FileUtils.splice) on a device/VM where Os.splice cannot be resolved reflectively or the invocation fails reflectively; custom ROMs or stripped frameworks missing the method; InvocationTargetException thrown from splice itself is rethrown as-is, so ENOSYS only comes from reflection failures.
Common situations: Running on emulators or modified Android builds lacking Os.splice; proguard/R8 renaming interfering with reflection when subclassing; testing splice paths on API < 28 without guards.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- Could not get backup files.
- Could not retrieve metadata from backup.
- Failed to create checksum file.
- Failed to write metadata.
- Failed to write checksums.txt
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/cca3466312d820c8.
Report an issue: GitHub.