juicedata/juicefs · error · IOException

write

Error message

write

What it means

FSOutputStream.write(byte[], int, int) calls the native jfs_write through JNI. If the native call returns a non-negative value smaller than the requested length, the library throws a plain IOException("write") because a partial write means the underlying JuiceFS writer did not accept all bytes and data would otherwise be silently lost.

Source

Thrown at sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java:1322

      int r = lib.jfs_fsync(Thread.currentThread().getId(), fd);
      if (r == EINVAL)
        throw new IOException("stream was closed");
      if (r < 0)
        throw error(r, path);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
      if (b.length - off < len) {
        throw new IndexOutOfBoundsException();
      }
      int done = lib.jfs_write(Thread.currentThread().getId(), fd, ByteBuffer.wrap(b, off, len), len);
      if (done == EINVAL)
        throw new IOException("stream was closed");
      if (done < 0)
        throw error(done, path);
      if (done < len) {
        throw new IOException("write");
      }
    }

    @Override
    public void write(int b) throws IOException {
      int done = lib.jfs_write(Thread.currentThread().getId(), fd, ByteBuffer.wrap(new byte[]{(byte) b}), 1);
      if (done == EINVAL)
        throw new IOException("stream was closed");
      if (done < 0)
        throw error(done, path);
      if (done < 1)
        throw new IOException("write");
    }
  }

  static class BufferedFSOutputStream extends BufferedOutputStream implements Syncable {
    private String hflushMethod;
    private boolean closed;

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Check the native client logs (juicefs mount/java-sdk log) for the underlying write error preceding the short write
  2. Retrying the write on a fresh stream: close the stream, re-create the file with overwrite and re-write the data
  3. Verify the JNI library version matches the juicefs version (mixing versions can cause misbehaving jfs_write)
  4. Buffer writes into chunks <= a few MB rather than one very large array

Example fix

// before
out.write(hugeBuffer); // may throw IOException("write") on short write
// after
int off = 0;
while (off < hugeBuffer.length) {
  int chunk = Math.min(4 * 1024 * 1024, hugeBuffer.length - off);
  out.write(hugeBuffer, off, chunk);
  off += chunk;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (b == null || off < 0 || len < 0 || b.length - off < len) throw new IllegalArgumentException("bad write buffer bounds");

Try / catch

try {
  out.write(buf, off, len);
} catch (IOException e) {
  if ("write".equals(e.getMessage())) {
    // short write: recreate stream and retry
    recreateAndRewrite(file, buf, off, len);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling OutputStream.write(byte[], off, len) (directly or through a buffering wrapper flushing to the FSOutputStream) when the native layer accepts fewer bytes than requested — e.g. the write-back cache failed to enqueue the data or an internal native-side error caused a short write.

Common situations: Copying files with FileSystem.copyFromLocalFile or IOUtils.copyBytes into JuiceFS when the native client hits an internal buffer limit; writing large byte arrays whose length exceeds the native chunk writer capacity; native library memory pressure.

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 juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/1b5e15919de91675. Report an issue: GitHub.