[GH-ISSUE #6957] [Bug] Regex worker cancellations drop the caller's abort reason #4247

Closed
opened 2026-10-31 00:48:04 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @viniciusdsandrade on GitHub (Oct 24, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6957

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

Source-only finding at main 1d896e03b; no runtime was executed.

matchRegexValues in src/process/RegexMatcher.ts builds its cancellation errors without the caller's abort reason at both producing sites:

  • the pre-admission refusal, return err(new AnalysisCancelledError(input.operation)) (line 536);
  • the abort listener armed while the worker runs, finish(err(new AnalysisCancelledError(input.operation))) (line 566).

The Hopper regex search returns that result unchanged (src/hopper/HopperRegexSearch.ts line 147, if (!matched.ok) return matched;), while its own checkpoint four lines later passes cause: options.signal.reason. HopperProvider forwards the search result as the operation result (src/hopper/HopperProvider.ts lines 395 to 397). A regex search_procedures or search_strings cancelled through Hopper therefore reports cancelled with cause === undefined, although the exact object given to AbortController.abort(reason) is still on the signal. The IDA client repairs a missing cause at its failure boundary (src/ida/IdaSessionClient.ts lines 453 to 456); the Kuna query path was not traced.

Reproduction

Not executed. Proposed check from source:

  1. Call matchRegexValues({ operation: "search_procedures", pattern: ".", caseSensitive: true, values: ["value"], signal: AbortSignal.abort(reason) }) with a distinct reason object.
  2. Call it again with a pending AbortController signal and abort with a second reason after the call starts.
  3. Source predicts both results are AnalysisCancelledError with cause === undefined.

Expected behavior

Both cancellation outcomes carry the caller's signal.reason as the error cause, the convention the repository adopted for the other producing sites in #6144 and that HopperRegexSearch already follows for the cancellation it observes itself.

Impact and scope

Bounded diagnostic loss: callers cannot tell which cancellation source stopped a regex search, and the identity of the abort reason is lost at the Hopper boundary. Cancellation classification and worker teardown are unaffected. Frequency in real sessions was not measured.

REA version

Source revision 1d896e03b (package metadata 6.7.0).

Runtime and platform

Not applicable; source inspection only.

Target and artifact context

Not applicable.

Interface

Other

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

Source references at 1d896e03b:

  • src/process/RegexMatcher.ts lines 535 to 536 and 565 to 566: the two constructions without cause.
  • src/hopper/HopperRegexSearch.ts lines 147 to 151: the matcher result is returned unchanged, then the next checkpoint passes cause: options.signal.reason.
  • src/hopper/HopperProvider.ts lines 395 to 397: the regex search result is the provider result.

NOT_ENOUGH_INFO for runtime output: the proposed check was not run.

Typed outcome or recovery expected

AnalysisCancelledError whose cause is the identical reason object at both sites.

Analysis or suspected cause

Source-derived: the producer never reads input.signal.reason. Passing { cause: input.signal.reason } at both constructions fixes every consumer at once, since Hopper, IDA, and Kuna share this matcher.

Originally created by @viniciusdsandrade on GitHub (Oct 24, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6957 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Native analysis or decompilation ## Observed behavior Source-only finding at main `1d896e03b`; no runtime was executed. `matchRegexValues` in `src/process/RegexMatcher.ts` builds its cancellation errors without the caller's abort reason at both producing sites: - the pre-admission refusal, `return err(new AnalysisCancelledError(input.operation))` (line 536); - the abort listener armed while the worker runs, `finish(err(new AnalysisCancelledError(input.operation)))` (line 566). The Hopper regex search returns that result unchanged (`src/hopper/HopperRegexSearch.ts` line 147, `if (!matched.ok) return matched;`), while its own checkpoint four lines later passes `cause: options.signal.reason`. `HopperProvider` forwards the search result as the operation result (`src/hopper/HopperProvider.ts` lines 395 to 397). A regex `search_procedures` or `search_strings` cancelled through Hopper therefore reports `cancelled` with `cause === undefined`, although the exact object given to `AbortController.abort(reason)` is still on the signal. The IDA client repairs a missing cause at its failure boundary (`src/ida/IdaSessionClient.ts` lines 453 to 456); the Kuna query path was not traced. ## Reproduction Not executed. Proposed check from source: 1. Call `matchRegexValues({ operation: "search_procedures", pattern: ".", caseSensitive: true, values: ["value"], signal: AbortSignal.abort(reason) })` with a distinct `reason` object. 2. Call it again with a pending `AbortController` signal and abort with a second reason after the call starts. 3. Source predicts both results are `AnalysisCancelledError` with `cause === undefined`. ## Expected behavior Both cancellation outcomes carry the caller's `signal.reason` as the error `cause`, the convention the repository adopted for the other producing sites in #6144 and that `HopperRegexSearch` already follows for the cancellation it observes itself. ## Impact and scope Bounded diagnostic loss: callers cannot tell which cancellation source stopped a regex search, and the identity of the abort reason is lost at the Hopper boundary. Cancellation classification and worker teardown are unaffected. Frequency in real sessions was not measured. ## REA version Source revision 1d896e03b (package metadata 6.7.0). ## Runtime and platform Not applicable; source inspection only. ## Target and artifact context Not applicable. ## Interface Other ## Earliest failure stage Cleanup, cancellation, or lifecycle ## Relevant output or evidence Source references at 1d896e03b: - `src/process/RegexMatcher.ts` lines 535 to 536 and 565 to 566: the two constructions without `cause`. - `src/hopper/HopperRegexSearch.ts` lines 147 to 151: the matcher result is returned unchanged, then the next checkpoint passes `cause: options.signal.reason`. - `src/hopper/HopperProvider.ts` lines 395 to 397: the regex search result is the provider result. NOT_ENOUGH_INFO for runtime output: the proposed check was not run. ## Typed outcome or recovery expected `AnalysisCancelledError` whose `cause` is the identical reason object at both sites. ## Analysis or suspected cause Source-derived: the producer never reads `input.signal.reason`. Passing `{ cause: input.signal.reason }` at both constructions fixes every consumer at once, since Hopper, IDA, and Kuna share this matcher.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4247
No description provided.