apache/iceberg · error · NotFoundException

Failed to open input stream for file: %s

Error message

Failed to open input stream for file: %s

What it means

HadoopInputFile.newStream opens a SeekableInputStream via fs.open(path). FileNotFoundException becomes NotFoundException (a missing file), while any other IOException becomes this RuntimeIOException. Both use the same 'Failed to open input stream' message, so check the exception type/cause to distinguish missing-file from I/O trouble.

Source

Thrown at core/src/main/java/org/apache/iceberg/hadoop/HadoopInputFile.java:187

      }
    }
    return stat;
  }

  @Override
  public long getLength() {
    if (length == null) {
      this.length = lazyStat().getLen();
    }
    return length;
  }

  @Override
  public SeekableInputStream newStream() {
    try {
      return HadoopStreams.wrap(fs.open(path));
    } catch (FileNotFoundException e) {
      throw new NotFoundException(e, "Failed to open input stream for file: %s", path);
    } catch (IOException e) {
      throw new RuntimeIOException(e, "Failed to open input stream for file: %s", path);
    }
  }

  @Override
  public Configuration getConf() {
    return conf;
  }

  @Override
  public void serializeConfWith(
      Function<Configuration, SerializableSupplier<Configuration>> confSerializer) {
    throw new UnsupportedOperationException("Cannot serialize a Hadoop input file: " + location());
  }

  public FileSystem getFileSystem() {
    return fs;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check the exception cause: FileNotFoundException means the file is gone — refresh table metadata or restore the file.
  2. Other causes (throttling, auth, permissions): refresh credentials, verify permissions, and retry with backoff.
  3. Ensure cleanup jobs don't delete files still covered by active snapshots; set proper retention windows.
  4. Confirm scheme/authority/region configuration matches the storage where files were written.
  5. Use table rollback to a snapshot whose files still exist if files were permanently lost.

Example fix

// before
SeekableInputStream in = io.newInputFile(path).newStream();
// after
try {
  SeekableInputStream in = io.newInputFile(path).newStream();
} catch (NotFoundException e) {
  table.refresh(); // metadata may reference a deleted file
  throw e;
} catch (RuntimeIOException e) {
  // transient FS/auth issue: refresh creds and retry
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

InputFile f = io.newInputFile(path);
if (!f.exists()) { /* avoid newStream: file missing */ }

Try / catch

try (SeekableInputStream in = io.newInputFile(path).newStream()) {
  // read
} catch (NotFoundException e) {
  // file missing: refresh metadata / rollback snapshot
} catch (RuntimeIOException e) {
  // transient IO/auth: refresh creds, retry with backoff
}

Prevention

When it happens

Trigger: Calling newStream() on a file deleted between exists() and open, on a path with wrong scheme/authority, or when the FS client fails (auth expiry, throttling, permission denied, checksum errors on HDFS).

Common situations: Readers racing with expireSnapshots/orphan cleanup; long-running Spark jobs whose Kerberos or cloud credentials expire; S3 throttling during large parallel reads; cluster decommissioning making files unreachable.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/8a03835bc920bcc6. Report an issue: GitHub.