{"record":{"id":"ac99a44d170ad77b","repo":"denoland/deno","slug":"failed-to-create-editor-ac99a4","errorCode":null,"errorMessage":"Failed to create editor.","messagePattern":"Failed to create editor\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"runtime/ops/tty.rs","lineNumber":501,"sourceCode":"    _: &Event,\n    _: RepeatCount,\n    _: bool,\n    _: &EventContext,\n  ) -> Option<Cmd> {\n    self.interrupted_by_esc.store(true, Relaxed);\n    Some(Cmd::Interrupt)\n  }\n}\n\n#[op2]\n#[string]\npub fn op_read_line_prompt(\n  #[string] prompt_text: &str,\n  #[string] default_value: &str,\n) -> Result<Option<String>, JsReadlineError> {\n  let _terminal_input_guard = deno_permissions::prompter::lock_terminal_input();\n  let mut editor = Editor::<(), rustyline::history::DefaultHistory>::new()\n    .expect(\"Failed to create editor.\");\n\n  editor.set_keyseq_timeout(Some(1));\n  let interrupted_by_esc = Arc::new(AtomicBool::new(false));\n  editor.bind_sequence(\n    KeyEvent(KeyCode::Esc, Modifiers::empty()),\n    EventHandler::Conditional(Box::new(PromptEscEventHandler {\n      interrupted_by_esc: interrupted_by_esc.clone(),\n    })),\n  );\n\n  let read_result =\n    editor.readline_with_initial(prompt_text, (default_value, \"\"));\n  match read_result {\n    Ok(line) => Ok(Some(line)),\n    Err(ReadlineError::Interrupted) => {\n      if interrupted_by_esc.load(Relaxed) {\n        return Ok(None);\n      }","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/runtime/ops/tty.rs#L483-L519","documentation":"op_read_line_prompt backs Deno.prompt(message, defaultValue): when stdin is a terminal, Deno builds a rustyline Editor so the default value is editable inline. Editor::new() returns an error when the terminal cannot be initialized (no usable TTY/termios environment), and this expect() panics. So the JS-side isTerminal() check can pass while rustyline still fails — e.g. a PTY-attached stdin in a container without a usable controlling terminal or /dev/tty.","triggerScenarios":"Calling `Deno.prompt(\"Name\", \"stranger\")` (any prompt with a default) in an environment where stdin looks like a terminal but rustyline cannot init: minimal containers with a pty but missing /dev/tty, daemons/cron with a pseudo-terminal, some CI harnesses, or Windows console redirection edge cases. Deno.prompt without a default does not use this op.","commonSituations":"Interactive CLI tools exercised inside docker exec / debug-sidecar PTYs where /dev/tty is absent; scripts run from IDE test runners that allocate a pipe-like pty; SSH sessions with broken TERM values; automation that pipes input while a wrapper fakes a TTY (node-pty style) without a controlling terminal.","solutions":["Run the script in a real interactive terminal (a proper login shell/SSH session with a controlling TTY).","Guard with a fallback: only call Deno.prompt(message, default) when `Deno.stdin.isTerminal()`, and additionally be prepared for exotic environments by supporting a plain `Deno.prompt(message)` path or reading stdin lines yourself.","Set a sane TERM (e.g. `TERM=xterm-256color`) in containerized/pty environments before running.","In CI/automation, avoid the default-value prompt form entirely; accept flags or env vars instead."],"exampleFix":"// before\nconst name = Deno.prompt(\"Your name\", \"stranger\"); // panics in pty-less container\n\n// after\nconst name = Deno.stdin.isTerminal()\n  ? (Deno.prompt(\"Your name\", \"stranger\") ?? \"stranger\")\n  : (new TextDecoder().decode(await readAllStdin()).trim() || \"stranger\");","handlingStrategy":"validation","validationCode":"async function promptSafe(message: string, def: string): Promise<string> {\n  if (!Deno.stdin.isTerminal()) return def;\n  try {\n    return Deno.prompt(message, def) ?? def;\n  } catch {\n    return def; // note: a native panic is NOT catchable; prefer flag/env input in exotic environments\n  }\n}","typeGuard":"const canPromptInteractively = () => Deno.stdin.isTerminal() && Deno.env.get(\"TERM\") !== undefined;","tryCatchPattern":null,"preventionTips":["In containers/CI, prefer flags or env vars over Deno.prompt(message, default).","Ensure a real controlling terminal and a valid TERM before offering the editable-default prompt.","Offer a non-default Deno.prompt(message) path (different code path, no rustyline) as a fallback."],"tags":["tty","prompt","rustyline","terminal","interactive","panic"],"backgroundTag":"terminal-initialization-failed","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}