run-llama/liteparse · error · std::io::Error

no data on stdin (input `-` expects a document piped in…

Error message

no data on stdin (input `-` expects a document piped in, e.g. `curl … | lit parse -`)

What it means

The core Rust CLI binary reads the full document from stdin when the input argument is `-`, and returns an `UnexpectedEof` io::Error if nothing was piped in. The dedicated error message makes the common mistake — passing `-` with no piped input — immediately diagnosable instead of failing later in the parser.

Solutions

  1. Pipe a real document: `curl -sL <url> | lit parse -`
  2. Enable pipefail so upstream failures abort before the CLI runs: `set -euo pipefail`
  3. Pass a file path directly instead of `-` when the document is on disk
  4. Confirm the producer emitted bytes (`wc -c`) before piping

Example fix

// before
lit parse - < /dev/null
// after
set -euo pipefail
curl -fsSL "$URL" | lit parse -
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
set -euo pipefail
curl -fsSL "$URL" | lit parse -   # -f fails on HTTP errors; pipefail propagates

Try / catch

if ! out=$(curl -fsSL "$URL"); then
  echo "download failed" >&2; exit 1
fi
printf '%s' "$out" | lit parse -

Prevention

When it happens

Trigger: Invoking the `liteparse` CLI with `-` as the input path while stdin is empty: interactive terminal invocation with no pipe, a dead/silent upstream producer (`curl` failing silently), or stdin redirected from an empty file.

Common situations: CI scripts where an upstream download step produced no output, shell examples pasted without the curl part, scripts reading from a FIFO that closed with no writes.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08). Data as JSON: /api/errors/db5fcedfca6d9d55. Report an issue: GitHub.

Appendix: source

Thrown at crates/liteparse/src/main.rs:362

        "text" => Ok(OutputFormat::Text),
        "markdown" | "md" => Ok(OutputFormat::Markdown),
        _ => Err(format!(
            "unknown format '{}', expected 'json', 'text', or 'markdown'",
            s
        )),
    }
}

/// Parse a `Name: Value` header string into a `(name, value)` pair.
/// Read all bytes from stdin, used when the input path is `-` (e.g. a piped
/// document: `curl -sL … | lit parse -`). Errors carry a hint so a common
/// mistake — passing `-` with nothing piped — is diagnosable.
fn read_stdin_bytes() -> Result<Vec<u8>, std::io::Error> {
    use std::io::Read;
    let mut bytes = Vec::new();
    std::io::stdin().lock().read_to_end(&mut bytes)?;
    if bytes.is_empty() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::UnexpectedEof,
            "no data on stdin (input `-` expects a document piped in, e.g. `curl … | lit parse -`)",
        ));
    }
    Ok(bytes)
}

fn parse_header(s: &str) -> Result<(String, String), String> {
    let (name, value) = s
        .split_once(':')
        .ok_or_else(|| format!("invalid header '{}', expected 'Name: Value'", s))?;
    let name = name.trim();
    if name.is_empty() {
        return Err(format!("invalid header '{}', empty header name", s));
    }
    Ok((name.to_string(), value.trim().to_string()))
}

View on GitHub (pinned to 22d2dd8cd7)