Skip to content

Legacy workflow editor crashes when AI assistant streams #4719

@elias-ba

Description

@elias-ba

What's broken

In the legacy workflow editor (WorkflowLive.Edit, served from /w/new/legacy and /w/:id/legacy), handle_info({:ai_assistant, action, payload}, socket) does a case action over :canvas_state_changed, :workflow_params_changed, :message_status_changed, :register_component, :unregister_component. There is no fallthrough.

When the legacy AI assistant LiveComponent registers, the parent LV subscribes to ai_session:#{session_id} so it can relay :message_status_changed back to the LiveComponent. That relay is what tells the spinner to stop and renders the finished message. The same PubSub topic also carries the four streaming events used by the collaborative editor: :streaming_status, :streaming_chunk, :streaming_changes, :streaming_error. These were added later for the React side and the legacy case never grew clauses for them. As soon as Apollo emits the first event (typically a :streaming_status "Thinking..."), the LV crashes with CaseClauseError.

How it surfaced

Sentry on v2.16.2, 1 event so far: LIGHTNING-1MV. Breadcrumbs show :register_component for a new AI session, then :streaming_status with text: "Thinking...", then the crash in LightningWeb.WorkflowLive.Edit.handle_info/2.

The two AI assistants are wired very differently:

  • The legacy editor uses the server-rendered LightningWeb.AiAssistant.Component LiveComponent. It does not display character-by-character streaming. It shows a static loading indicator and then renders the finished message once :message_status_changed arrives. The only PubSub event it actually consumes is :message_status_changed.
  • The collaborative editor is pure React. The collab LV does not subscribe to ai_session:* at all. Its React side joins LightningWeb.AiAssistantChannel, which is where the four streaming events are consumed and rendered as the typewriter effect via a Zustand store.

Because the streaming events still flow through the shared ai_session:#{session_id} PubSub topic, they reach the legacy LV by accident, and that is what crashes it.

What to fix

Minimal fix: add a catch-all clause to the case in Edit.handle_info({:ai_assistant, ...}) so unknown actions are dropped silently. The legacy LV consumes none of the four streaming events, so dropping them is correct and does not change any user-visible behaviour. :message_status_changed continues to be handled and remains the relay that lets the LiveComponent finish loading.

A cleaner option, not subscribing the legacy LV to ai_session:* at all and routing :message_status_changed through a narrower channel, is more invasive than the deprecation timeline of the legacy editor warrants.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

In review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions