MuntashirAkon/AppManager · error · IllegalArgumentException

Negative position

Error message

Negative position

What it means

RemoteFileChannel.read(ByteBuffer, long position) throws IllegalArgumentException("Negative position") when the absolute read position is negative, per the FileChannel positional-read contract. The check runs before ensureOpen and any remote IPC.

Solutions

  1. Validate/clamp position to >= 0 before the call (Math.max(0, position)).
  2. Fix the offset computation so the saved/derived position cannot go negative.
  3. Check state-restore code that loads positions from storage for corruption handling.
  4. Assert position >= 0 in the reader loop for early, clear failures.

Example fix

// before
channel.read(buffer, lastPos - chunkSize);
// after
long pos = Math.max(0, lastPos - chunkSize);
channel.read(buffer, pos);
Defensive patterns

Strategy: validation

Validate before calling

if (position < 0) {
    throw new IllegalArgumentException("read position must be >= 0, got " + position);
}
channel.read(dst, position);

Try / catch

try {
    channel.read(dst, position);
} catch (IllegalArgumentException e) {
    logger.warn("Bad read position {}", position, e);
}

Prevention

When it happens

Trigger: Calling read(dst, position) with position < 0, e.g. from cursor arithmetic like position - skip where skip exceeded position, or a parsed offset that failed.

Common situations: Chunked readers computing offsets with off-by-one/negative deltas; restoring a saved read position from corrupted state; using Long.MIN_VALUE sentinels.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/RemoteFileChannel.java:330

        long bytes = 0;
        while (count > bytes) {
            int limit = (int) Math.min(b.capacity(), count - bytes);
            b.limit(limit);
            if (src.read(b) <= 0)
                break;
            b.flip();
            int len = write0(b, position);
            position += len;
            bytes += len;
            b.clear();
        }
        return bytes;
    }

    @Override
    public int read(ByteBuffer dst, long position) throws IOException {
        if (position < 0)
            throw new IllegalArgumentException("Negative position");
        ensureOpen();
        return read0(dst, position);
    }

    @Override
    public int write(ByteBuffer src, long position) throws IOException {
        if (position < 0)
            throw new IllegalArgumentException("Negative position");
        ensureOpen();
        return write0(src, position);
    }

    @Override
    protected void implCloseChannel() {
        try { fs.close(handle); } catch (RemoteException ignored) {}
        synchronized (fdLock) {
            try { Os.close(read); } catch (ErrnoException ignored) {}
            try { Os.close(write); } catch (ErrnoException ignored) {}

View on GitHub (pinned to 0152f468fc)