conductor-oss/conductor · error · RuntimeException

Failed to read InputStream for upload

Error message

Failed to read InputStream for upload

What it means

Thrown by the default DocumentLoader.upload(Map,String,InputStream,String) when InputStream.readAllBytes() raises an IOException. The default implementation buffers the whole stream into memory then delegates to the byte[]-based upload; this exception means the stream itself was unreadable, not that the upload failed. RuntimeException wrapping the IOException.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/document/DocumentLoader.java:38

public interface DocumentLoader {

    byte[] download(String location);

    String upload(Map<String, String> headers, String contentType, byte[] data, String fileURI);

    /**
     * Upload data from an InputStream, allowing streaming of large files (e.g., video) without
     * buffering the entire content in memory.
     *
     * <p>Default implementation reads all bytes into memory and delegates to the byte[]-based
     * upload. Implementations should override this for true streaming behavior.
     */
    default String upload(
            Map<String, String> headers, String contentType, InputStream data, String fileURI) {
        try {
            return upload(headers, contentType, data.readAllBytes(), fileURI);
        } catch (IOException e) {
            throw new RuntimeException("Failed to read InputStream for upload", e);
        }
    }

    List<String> listFiles(String location);

    boolean supports(String location);
}

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Ensure the InputStream is open, at position 0, and readable when passed (do not double-consume or pass a closed stream).
  2. For large files, override upload(...) in your DocumentLoader to stream instead of buffering (avoid readAllBytes entirely).
  3. Wrap the source so read failures surface a meaningful cause; check getCause() for the real IOException.
  4. If memory is the issue (huge files), use a streaming implementation rather than the default in-memory one.

Example fix

// before — stream already used
InputStream is = Files.newInputStream(path);
is.readAllBytes();
loader.upload(headers, ct, is, uri); // closed/exhausted -> error
// after — fresh stream
loader.upload(headers, ct, Files.newInputStream(path), uri);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the stream is fresh and readable before upload
if (data == null) throw new IllegalArgumentException("InputStream is null");
// best: open a new stream per call, e.g. Files.newInputStream(path)
loader.upload(headers, contentType, Files.newInputStream(path), fileURI);

Try / catch

try {
    loader.upload(headers, contentType, inputStream, fileURI);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof java.io.IOException io) {
        log.error("Could not read upload stream: {}", io.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: A closed, already-consumed, or broken InputStream is passed to upload(); the underlying source throws during read (e.g. a socket/pipe that closed, a truncated file, a stream from a resource that was freed).

Common situations: Reusing a stream that was already read once; passing a stream from a try-with-resources that has been closed; reading from a network/socket source that drops mid-transfer; very large streams failing on memory exhaustion during readAllBytes.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/4fddf34d9d939fe5. Report an issue: GitHub.