denoland/deno · error · AnyError

Failed to read from stdin

Error message

Failed to read from stdin

What it means

When linting standard input (`deno lint -`), Deno reads all of stdin into a string before linting; if read_to_string fails — stdin closed or unreadable, an OS-level read error, or non-UTF-8 bytes — it aborts with this message. The underlying io::Error is swallowed, so the wording stays generic.

Source

Thrown at cli/tools/lint/mod.rs:613

) -> Result<bool, AnyError> {
  let start_dir = &cli_options.start_dir;
  let reporter_lock = Arc::new(Mutex::new(create_reporter(
    workspace_lint_options.reporter_kind,
  )));
  let lint_config = start_dir
    .to_lint_config(FilePatterns::new_with_base(start_dir.dir_path()))?;
  let deno_lint_config =
    resolve_lint_config(compiler_options_resolver, start_dir.dir_url())?;
  let lint_options = LintOptions::resolve(lint_config, &lint_flags)?;
  let configured_rules = lint_rule_provider
    .resolve_lint_rules_err_empty(lint_options.rules, Some(start_dir))?;
  let mut file_path = cli_options.initial_cwd().join(STDIN_FILE_NAME);
  if let Some(ext) = cli_options.ext_flag() {
    file_path.set_extension(ext);
  }
  let mut source_code = String::new();
  if stdin().read_to_string(&mut source_code).is_err() {
    return Err(anyhow!("Failed to read from stdin"));
  }

  let linter = CliLinter::new(CliLinterOptions {
    fix: false,
    configured_rules,
    deno_lint_config,
    maybe_plugin_runner: None,
  });

  let r = linter.lint_file(&file_path, deno_ast::strip_bom(source_code), None);

  let success =
    handle_lint_result(&file_path.to_string_lossy(), r, reporter_lock.clone());
  reporter_lock.lock().close(1);
  Ok(success)
}

fn handle_lint_result(

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Make sure input is actually piped: `deno lint - < src/mod.ts` or `echo 'const x = 1;' | deno lint -`
  2. Ensure the stream is UTF-8 text — decompress and strip binaries before piping
  3. In scripts, only use `-` when input is guaranteed (test that stdin is a pipe first)

Example fix

# before (CI, stdin never attached)
deno lint -

# after
deno lint - < src/mod.ts
Defensive patterns

Strategy: validation

Validate before calling

// only pass '-' when stdin is a pipe with data available
const st = await Deno.stat('/dev/stdin').catch(() => null);
const isPipe = st !== null && !st.isTerminal;
if (!isPipe) {
  console.error('nothing piped into deno lint -');
  Deno.exit(1);
}

Prevention

When it happens

Trigger: `deno lint -` where stdin is not a readable pipe (no input attached in CI or service contexts), the upstream writer fails mid-stream (broken pipe), or the piped bytes are not valid UTF-8 (binary data, still-compressed output).

Common situations: CI jobs invoking `deno lint -` unconditionally with stdin closed; piping compressed or binary content by mistake (a forgotten gunzip); producers that exit before writing anything; terminal-less service environments.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/5fc9dc75cbeb19f6. Report an issue: GitHub.