MuntashirAkon/AppManager · error

IOException(errnoException)

Error message

IOException(errnoException)

What it means

LocalFile.createLink() creates a hard link or symlink via Os.link/Os.symlink. If the OS call fails with any ErrnoException other than EEXIST, it is rethrown as an IOException wrapping the ErrnoException. EEXIST alone returns false (link already exists), but all other kernel errors (missing parent dir, permission denied, cross-device link, etc.) surface as this IOException.

Source

Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/LocalFile.java:195

    public boolean createNewLink(String existing) throws IOException {
        return createLink(existing, false);
    }

    @Override
    public boolean createNewSymlink(String target) throws IOException {
        return createLink(target, true);
    }

    private boolean createLink(String target, boolean soft) throws IOException {
        try {
            if (soft)
                Os.symlink(target, getPath());
            else
                Os.link(target, getPath());
            return true;
        } catch (ErrnoException e) {
            if (e.errno != OsConstants.EEXIST) {
                throw new IOException(e);
            }
            return false;
        }
    }
}

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Check e.getCause()/errno on the IOException to identify the specific errno and fix accordingly (create parent dirs, correct target path)
  2. Ensure both target and link location are on the same filesystem for hard links, or use a symlink instead
  3. Verify write permission on the directory where the link is created

Example fix

// before
new LocalFile(dir, "link").createNewSymlink(target); // IOException(ErrnoException)
// after
File link = new LocalFile(dir, "link");
if (!link.getParentFile().exists() || !new File(target).exists()) {
    throw new IllegalStateException("missing target or parent dir");
}
boolean created = link.createNewSymlink(target); // returns false if already exists
Defensive patterns

Strategy: try-catch

Validate before calling

File linkFile = new LocalFile(dir, name);
if (!linkFile.getParentFile().canWrite()) throw new IOException("no write permission on " + dir);
if (!new File(target).exists()) throw new FileNotFoundException(target);

Type guard

boolean canCreateLinkIn(File dir, String target) { return dir.canWrite() && new File(target).exists(); }

Try / catch

try { boolean ok = file.createNewSymlink(target); } catch (IOException e) { if (e.getCause() instanceof ErrnoException) { int errno = ((ErrnoException) e.getCause()).errno; /* handle EACCES/EXDEV/ENOENT */ } }

Prevention

When it happens

Trigger: createNewLink()/createNewSymlink() when: the target file doesn't exist (ENOENT), the parent directory of the link path doesn't exist (ENOENT), the process lacks write permission on the directory (EACCES), linking across filesystems (EXDEV for hard links), or the filesystem doesn't support symlinks.

Common situations: Symlinking on FAT/sdcard FUSE mounts that forbid symlinks; creating links in app-external dirs without write permission; target moved/deleted between check and call; hard links across partitions.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/9e1ba5aaf19ddab4. Report an issue: GitHub.