Skip to content

Fix OSError [Errno 22] when running process without a TTY#3

Merged
nmbrthirteen merged 3 commits into
nmbrthirteen:mainfrom
rikitrader:fix/non-interactive-tty-guard
Jun 2, 2026
Merged

Fix OSError [Errno 22] when running process without a TTY#3
nmbrthirteen merged 3 commits into
nmbrthirteen:mainfrom
rikitrader:fix/non-interactive-tty-guard

Conversation

@rikitrader

@rikitrader rikitrader commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Problem

Running podcli process <video> in a non-interactive context (piped stdin, CI, a wrapper script, or another process driving the CLI) crashes with:

OSError: [Errno 22] Invalid argument
  ...
  File ".../prompt_toolkit/input/vt100.py", line 165, in _attached_input
    loop.add_reader(fd, callback_wrapper)

The clip-review step uses questionary/prompt_toolkit, which calls loop.add_reader() on stdin. That fails when stdin isn't a real terminal, so the whole render aborts even though transcription and clip detection already succeeded.

Fix

Guard the three interactive entry points with sys.stdin.isatty():

  • _review_clips() — renders all suggested clips (the same as the default "Render N selected clips" action) instead of launching the picker.
  • _should_enter_post_render_loop() — returns False so the post-render menu never opens.
  • per-clip _skip_review — forced True.

Interactive behavior in a real terminal is completely unchanged; this only affects the no-TTY path, which previously could only crash.

Testing

./podcli process clip.mp4 --top 1 --crop face --caption-style hormozi --quality max --no-speakers < /dev/null

  • Before: OSError: [Errno 22] during clip review.
  • After: exit 0 — transcribes, selects, and renders the clip headlessly.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed crashes when running the CLI with piped input or in non-interactive mode. The tool now correctly detects non-TTY environments and disables interactive prompts, instead rendering all output directly. This enables reliable use in automated workflows, scripts, CI/CD pipelines, and other non-interactive contexts where input cannot be interactively provided.

The `process` command's clip-picker uses questionary/prompt_toolkit,
which calls `loop.add_reader()` on stdin and raises `OSError: [Errno 22]
Invalid argument` when stdin is not a real terminal (piped input, CI,
scripted/automated runs, or when driven by another process).

Guard the three interactive entry points with `sys.stdin.isatty()`:
- `_review_clips()` renders all suggested clips instead of prompting
- `_should_enter_post_render_loop()` returns False
- per-clip `_skip_review` is forced True

Interactive behavior in a real terminal is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rikitrader rikitrader requested a review from nmbrthirteen as a code owner June 1, 2026 02:48
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nmbrthirteen, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 27 minutes and 35 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15efa059-4a73-4ef0-a776-ce407aea2609

📥 Commits

Reviewing files that changed from the base of the PR and between f7a1707 and 40def52.

📒 Files selected for processing (2)
  • backend/cli.py
  • tests/test_cli_output_dir.py
📝 Walkthrough

Walkthrough

The PR adds non-TTY stdin detection across three interactive entry points in the CLI: the clip review picker, the post-render loop, and the export review coordination. When stdin is piped (not a TTY), interactive prompts and UI pickers are bypassed to prevent crashes.

Changes

Non-TTY stdin non-interactive CLI mode

Layer / File(s) Summary
Clip review non-interactive path
backend/cli.py
_review_clips logs a message and returns the full clip list immediately when stdin is not a TTY, skipping the interactive questionary picker.
Post-render interactive loop guard
backend/cli.py
_should_enter_post_render_loop returns False early when stdin is not a TTY to prevent entering the interactive rerender flow.
Export review skip coordination
backend/cli.py
Export loop's _skip_review logic now also checks sys.stdin.isatty() to skip per-clip review prompts when input is piped.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~4 minutes

Poem

🐰 A pipe comes calling, no TTY in sight,
So bundle our prompts and render it right,
No picker, no loop, just return what we know,
The clips all flow smooth through the non-interactive flow! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: preventing OSError [Errno 22] when running the process command without a TTY by guarding interactive prompts.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

nmbrthirteen
nmbrthirteen previously approved these changes Jun 1, 2026

@nmbrthirteen nmbrthirteen left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Hey, You are the first contributor. Thanks a lot for this! Approved :))

@nmbrthirteen

Copy link
Copy Markdown
Owner

Pls check test error before merging

The TTY guard added in this PR makes _should_enter_post_render_loop return
False in non-interactive environments (incl. CI), so the config/interrupt
tests must force a TTY. Adds a test for the non-TTY guard itself.
@nmbrthirteen nmbrthirteen merged commit a5f8f4b into nmbrthirteen:main Jun 2, 2026
5 checks passed
nmbrthirteen added a commit that referenced this pull request Jun 2, 2026
* Fix OSError [Errno 22] when running `process` without a TTY

The `process` command's clip-picker uses questionary/prompt_toolkit,
which calls `loop.add_reader()` on stdin and raises `OSError: [Errno 22]
Invalid argument` when stdin is not a real terminal (piped input, CI,
scripted/automated runs, or when driven by another process).

Guard the three interactive entry points with `sys.stdin.isatty()`:
- `_review_clips()` renders all suggested clips instead of prompting
- `_should_enter_post_render_loop()` returns False
- per-clip `_skip_review` is forced True

Interactive behavior in a real terminal is unchanged.

* test: stabilize post-render-loop tests under the new TTY guard

The TTY guard added in this PR makes _should_enter_post_render_loop return
False in non-interactive environments (incl. CI), so the config/interrupt
tests must force a TTY. Adds a test for the non-TTY guard itself.

---------

Co-authored-by: Ricardo Prieto <ricardoprieto@ricardos-mbp.lan>
Co-authored-by: Nika Siradze <nikushasiradzee@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants