Skip to content

fix: validate graph sink nodes before stream start (#947)#948

Open
livepeer-tessa wants to merge 2 commits intomainfrom
fix/graph-no-sink-node-validation
Open

fix: validate graph sink nodes before stream start (#947)#948
livepeer-tessa wants to merge 2 commits intomainfrom
fix/graph-no-sink-node-validation

Conversation

@livepeer-tessa
Copy link
Copy Markdown
Contributor

Problem

Closes #947

When a user's graph contains only Output nodes (Spout/NDI/Syphon) and all of them have the Enabled toggle off, the frontend's flowToGraphConfig() skips them during serialization. The backend receives a graph with no sink nodes and throws:

Pipeline setup failed: Invalid graph: Graph must have at least one sink node

This was a cryptic server-side error with no UX guidance on how to fix it. Happened 1x on fal.ai prod at 15:58 UTC 2026-04-15 (job 0dddbac2).

Root Cause

In graphUtils.ts, Output nodes are in FRONTEND_ONLY_TYPES (filtered from backend serialization) and are only added back as type: "sink" nodes if outputSinkEnabled === true. A disabled Output node → no sink in the serialized graph.

Fix

Frontend (before-the-server-gets-it):

  • Added validateGraphForStream(nodes, edges) utility in graphUtils.ts that detects missing/disabled sinks
  • Exposed validateForStream() on GraphEditorHandle
  • handleStartStream() calls validation first → shows toast.error with actionable message
  • OutputNode shows amber warning banner when disabled

Backend (last-resort fallback):

  • Improved server-side error message in graph_schema.py with fix hint

Tests:

  • 10 unit tests in tests/test_graph_schema.py all passing

Testing

python -m pytest tests/test_graph_schema.py -v  # 10 passed

For manual testing: create a graph with only an Output node (Enabled=off) and try to start streaming → should see toast error instead of server failure.

Tessa (livepeer-tessa) added 2 commits April 15, 2026 06:16
Attempting to uninstall a bundled plugin is an expected, handled
condition — not a server-side failure. This was generating ERROR-level
log noise on every prod fal.ai job that triggered the cleanup path
(issue #837).

Changes:
- Add PluginBundledError(PluginInstallError) subclass in manager.py so
  callers can distinguish bundled-rejection from true install failures
- Raise PluginBundledError instead of PluginInstallError in
  _uninstall_plugin_sync when a bundled plugin is targeted
- In app.py uninstall endpoint, catch PluginBundledError before the
  generic PluginInstallError handler: log at WARNING, return HTTP 400
  (client error) instead of 500 (server error)

Fixes: #837
Signed-off-by: Tessa (livepeer-tessa) <tessa@livepeer.org>
…sages

Closes #947

Root cause: when a graph contains only Output nodes (Spout/NDI/Syphon)
and all of them have outputSinkEnabled=false, the serialization step in
flowToGraphConfig() skips them — leaving the backend graph with no sink
nodes, which triggers 'Invalid graph: Graph must have at least one sink
node' from frame_processor.

Changes:
- frontend/graphUtils.ts: add validateGraphForStream() utility that
  detects missing/disabled sink nodes and returns a human-readable error
  before the graph is submitted to the backend
- GraphEditor.tsx: expose validateForStream() on GraphEditorHandle so
  StreamPage can call it before starting the stream
- StreamPage.tsx: call validateForStream() in handleStartStream() for
  graph mode; show toast.error with actionable message instead of
  failing server-side
- OutputNode.tsx: show amber warning banner when output node is disabled,
  prompting user to enable it or add a Sink node
- graph_schema.py: improve the server-side error message to include
  remediation hint ('Add a Preview (Sink) node or enable an Output node')
  as a last line of defense
- tests/test_graph_schema.py: add 10 unit tests for validate_structure()
  including the user-friendly error message requirement

Signed-off-by: Tessa (livepeer-tessa) <tessa@livepeer.org>
@livepeer-tessa livepeer-tessa added the bug Something isn't working label Apr 15, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ea88e554-e32c-4a70-86a6-b333c7547aa2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/graph-no-sink-node-validation

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.

@github-actions
Copy link
Copy Markdown
Contributor

🚀 fal.ai Preview Deployment

App ID daydream/scope-pr-948--preview
WebSocket wss://fal.run/daydream/scope-pr-948--preview/ws
Commit 76b7cbc

Livepeer Runner

App ID daydream/scope-livepeer-pr-948--preview
WebSocket wss://fal.run/daydream/scope-livepeer-pr-948--preview/ws
Auth private

Testing Livepeer Mode

SCOPE_CLOUD_MODE=livepeer SCOPE_CLOUD_APP_ID="daydream/scope-livepeer-pr-948--preview/ws" uv run daydream-scope

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[fal.ai] frame_processor: Pipeline setup fails — 'Invalid graph: Graph must have at least one sink node'

1 participant