Skip to content

[APP-5287] Fix char-boundary panic in workflow AI context menu preview - #14935

Closed
warp-agent-staging[bot] wants to merge 1 commit into
masterfrom
oz/app-5287-workflow-preview-panic
Closed

[APP-5287] Fix char-boundary panic in workflow AI context menu preview#14935
warp-agent-staging[bot] wants to merge 1 commit into
masterfrom
oz/app-5287-workflow-preview-panic

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes a production panic reported in Sentry (WARP-CLIENT-BETA-STABLE-87EV): WorkflowDataSource::run_query panics with byte index 197 is not a char boundary whenever a workflow's content preview has a multi-byte UTF-8 character (emoji, CJK, accented character, etc.) straddling the fixed byte offset 197.

WorkflowDataSource::run_query builds a ~200-char description preview from the first 3 lines of a workflow's content and truncates it with a fixed byte slice &content_preview[..197]. Rust panics if that index falls inside a multi-byte character instead of on a char boundary. run_query executes when the @ context menu's Workflows category is opened or a query is run against it (not merely on the bare @ zero state before a category is selected), so any user with a workflow whose preview has a multi-byte character straddling byte 197 crashes the app the moment they open the Workflows category or search within it.

Note for anyone reproducing this later: run_query reads workflows from CloudModel (Warp Drive), not the local workflow loaders, so a repro needs the workflow to exist in Warp Drive rather than as a local YAML file on disk.

The sibling notebooks/data_source.rs was already fixed for the same class of bug, and the repo has an existing safe_truncate helper (app/src/search/ai_context_menu/mod.rs) built exactly for char-boundary-safe truncation - it's already used by the render-path search_item.rs files. This PR reuses that helper in WorkflowDataSource::run_query instead of hand-rolling new truncation logic, preserving the existing ~200-char preview + ... behavior. notebooks/data_source.rs's existing char_indices-based truncation was left as-is since its computed endpoint is already a valid char boundary and isn't affected by this bug.

I audited the rest of ai_context_menu/ for the same fixed-byte-slice pattern and found no other unsafe instance; the only report was this one spot in workflows/data_source.rs.

Linked Issue

Linear: APP-5287 - https://linear.app/warpdotdev/issue/APP-5287/panic-byte-index-is-not-a-char-boundary-in-workflowdatasourcerun-query
Sentry: https://warpdotdev.sentry.io/issues/7665761472/

  • Reproduced and root-caused via triage; no separate GitHub issue exists.
  • Screenshots/video included below (crash fix, verified via computer use).

Testing

Added run_query_does_not_panic_on_multibyte_content_preview in app/src/search/ai_context_menu/workflows/data_source.rs (new data_source_tests.rs), which builds a workflow whose content is 195 ASCII bytes + a 4-byte emoji (straddling byte 197) + trailing text, inserts it into a mocked CloudModel, and calls WorkflowDataSource::run_query.

  • Confirmed the test panics on the pre-fix code with the exact Sentry panic message: byte index 197 is not a char boundary; it is inside '🚀' (bytes 195..199).
  • Confirmed the test passes after the fix.
  • cargo nextest run -p warp -E 'test(run_query_does_not_panic_on_multibyte_content_preview)' - 1 passed
  • cargo nextest run -p warp -E 'test(ai_context_menu::workflows) or test(ai_context_menu::notebooks)' - 6 passed (no regressions in the sibling notebooks data source)
  • cargo fmt -- --check - clean
  • cargo clippy -p warp --all-targets --tests -- -D warnings - clean

Additionally verified end-to-end with computer use, using a Warp Drive workflow named "Char boundary repro APP-5287" whose content is 241 bytes: 195×a + 🚀 at bytes 195-198 + -BOUNDARY-TAIL-PADDING-TO-EXCEED-200-BYTES.

  • I have manually tested my changes locally with ./script/run (via a computer-use verification agent)

Screenshots / Videos

Fixed branch (oz/app-5287-workflow-preview-panic) - no crash:

https://oz.staging.warp.dev/artifacts/019ff146-9d8f-72ee-b741-b9b6f911078f

@ → zero-state menu → Workflows → the repro workflow "Char boundary repro APP-5287" renders with its truncated preview → typing char boundary filters to it → Escape → input still accepts text.

master (cd49bd7), same machine, same workflow - crashes:

https://oz.staging.warp.dev/artifacts/019ff14c-2725-7821-91a7-b1973b08c5c0

@ → Workflows → the window vanishes instantly and never returns. Client log, verbatim:

[ERROR] [panic] thread 'main' panicked at 'byte index 197 is not a char boundary; it is inside '🚀' (bytes 195..199) of `aaaa…🚀-BOUNDARY-TAIL-PADDING-TO-EXCEED-200-BYTES`': app/src/search/ai_context_menu/workflows/data_source.rs:69

(fired immediately after AIContextMenuAction::CategorySelected { category: Workflows })

Screenshots:

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Conversation: https://staging.warp.dev/conversation/e2d7d084-0bd9-4afa-a852-950216116378
Run: https://oz.staging.warp.dev/runs/019ff0fd-37ae-7b2c-94ab-2edb6a41b2ce

This PR was generated with Oz.

Co-Authored-By: Warp Agent agent@warp.dev

WorkflowDataSource::run_query built the workflow description preview
by slicing content_preview at a fixed byte offset (197), which panics
with "byte index is not a char boundary" whenever a multi-byte UTF-8
character (emoji, CJK, accented char, etc.) straddles that offset.
This runs for every workflow on every `@` context menu query,
including the zero state, so any user with such a workflow crashes
the app.

Fix by reusing the existing safe_truncate helper (already used by the
sibling notebooks data source and by search_item render paths) which
truncates at the nearest valid char boundary instead of a fixed byte
index.

Fixes APP-5287.

Co-Authored-By: Warp Agent <agent@warp.dev>
@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

Heads up: this PR and #14933 are two independent fixes for the same panic (APP-5287), produced by two parallel agent runs, and both are attached to the issue. Only one should be merged.

They land on the same fix — safe_truncate in place of the raw &content_preview[..197] slice, plus a multibyte regression test. #14933 is already out of draft and has an extra short-content test; this PR carries the GUI verification (fixed-branch recording, master crash recording, and the verbatim panic log) and an accurate description of the trigger.

If the reviewer prefers #14933, the captures here apply to it unchanged and can be copied over.

@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

Closing in favor of #14933, at the reviewer's direction.

Both PRs are independent fixes for the same panic (APP-5287), produced by two parallel agent runs, and both make the same core change: replacing the raw &content_preview[..197] slice with safe_truncate. Only one should merge, and #14933 is the one under review.

The verification work here was not wasted. The recordings and the client log captured on this branch — master crashing the instant the Workflows category opens, and the fixed branch surviving the same click — have been carried over into #14933's description, since they are now that PR's proof the fix works. The factual correction from this branch also went into #14933: the panic does not fire on the bare @ zero state, and run_query reads workflows from CloudModel/Warp Drive rather than local YAML.

No code from this branch is lost — #14933 carries the equivalent fix.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant