apache/druid · error · org.apache.druid.java.util.common.IAE

Invalid arguments for reading

Error message

Invalid arguments for reading %s. from = %d, readSize = %d, fileSize = %d

What it means

LocalFileStorageConnector.readRange validates from >= 0, size >= 0, and from + size <= file length, throwing IAE with the resolved path, from, size, and actual file size when the requested window is invalid. It prevents out-of-bounds range reads on local files.

Solutions

  1. Fetch the current file length via the connector and clamp: size = min(size, length - from), rejecting negatives.
  2. Replace any 'read to end' sentinel (-1) with length - from before calling.
  3. Re-stat the file and retry if it changed concurrently between length check and read.
  4. Unit-test range math including edge cases from=length, size=0, and length=0 files.

Example fix

// before
connector.readRange(path, from, -1); // invalid
// after
long length = new File(basePath, path).length();
long readSize = (size < 0) ? length - from : Math.min(size, length - from);
if (from < 0 || readSize < 0) {
  throw new IAE("bad range: from=%d size=%d fileLen=%d", from, size, length);
}
connector.readRange(path, from, readSize);
Defensive patterns

Strategy: validation

Validate before calling

long len = new File(basePath, path).length();
if (from < 0 || size < 0 || from + size > len) throw new IllegalArgumentException("bad range " + from + "+" + size + ">" + len);

Try / catch

try { in = connector.readRange(path, from, size); } catch (IllegalArgumentException e) { log.warn(e, "invalid range for %s", path); in = connector.readRange(path, 0, new File(basePath, path).length()); }

Prevention

When it happens

Trigger: readRange with negative from or size, or from+size exceeding the file length: using content-length from a HEAD on a different file version, off-by-one (fileLength instead of fileLength-1), unbounded size sentinel (-1) passed through.

Common situations: HTTP Range header parsing producing wrong offsets; file truncated/changed between stat and read; client passing -1 as size for 'to end' which this API does not support.

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 apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/ea49817c5f22b50a. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/storage/local/LocalFileStorageConnector.java:78

  {
    return fileWithBasePath(path).exists();
  }

  @Override
  public InputStream read(String path) throws IOException
  {
    return Files.newInputStream(fileWithBasePath(path).toPath());
  }

  @Override
  public InputStream readRange(String path, long from, long size) throws IOException
  {
    if (!pathExists(path)) {
      throw new FileNotFoundException("Unable to find file " + fileWithBasePath(path).toPath() + " for reading");
    }
    long length = fileWithBasePath(path).length();
    if (from < 0 || size < 0 || (from + size) > length) {
      throw new IAE(
          "Invalid arguments for reading %s. from = %d, readSize = %d, fileSize = %d",
          fileWithBasePath(path).toPath(),
          from,
          size,
          length
      );
    }
    FileChannel fileChannel = FileChannel.open(fileWithBasePath(path).toPath(), StandardOpenOption.READ);
    return new BoundedInputStream(Channels.newInputStream(fileChannel.position(from)), size);
  }

  /**
   * Writes the file present with the materialized location as basePath + path.
   * In case the parent directory does not exist, we create the parent dir recursively.
   * Closing of the stream is the responsibility of the caller.
   *
   * @param path path to write contents to.
   * @return OutputStream which can be used by callers to write contents.

View on GitHub (pinned to 9b90983fd2)