apache/flink · error · IOException

Stream closed.

Error message

Stream closed.

What it means

Thrown by RefCountedFile.requireOpened() when an operation is attempted on a temp file reference whose `closed` flag is true. RefCountedFile is the reference-counted handle to the temp file backing recoverable writers; operating after close violates the lifecycle contract.

Source

Thrown at flink-core/src/main/java/org/apache/flink/core/fs/RefCountedFile.java:80

        if (references.decrementAndGet() == 0) {
            return tryClose();
        }
        return false;
    }

    private boolean tryClose() {
        try {
            Files.deleteIfExists(file.toPath());
            return true;
        } catch (Throwable t) {
            ExceptionUtils.rethrowIfFatalError(t);
        }
        return false;
    }

    private void requireOpened() throws IOException {
        if (closed) {
            throw new IOException("Stream closed.");
        }
    }

    public int getReferenceCounter() {
        return references.get();
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Audit retain()/release() balance: every retain must have a matching release, and operations must happen before the final release.
  2. After release(), drop the reference so it cannot be reused.
  3. Ensure single-ownership of the RefCountedFile handle or use proper retain before sharing across threads.
  4. In cancellation paths, drain outstanding writes before releasing.
Defensive patterns

Strategy: validation

Validate before calling

void useRefCountedFile(RefCountedFile f) throws IOException {
    if (f.getReferenceCounter() <= 0) throw new IllegalStateException("file already released");
    // operate on f
}

Try / catch

try {
    file.getPos();
} catch (IOException e) {
    if ("Stream closed.".equals(e.getMessage())) { /* handle released file */ return; }
    throw e;
}

Prevention

When it happens

Trigger: Calling getOutputStream/write/getPos (or any guarded op) on a RefCountedFile after release() decremented references to zero and closed it, or after an explicit close.

Common situations: Reference-counting misuse: releasing the last reference then attempting to use the file; concurrent release+write during cancellation; a bug where the same handle is shared and one owner closes while another writes.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/a93e8954d64587cc. Report an issue: GitHub.