Skip to content

FIX: preserve child-result links when execution fails in SequentialAttack - #3048

Merged
Roman Lutz (romanlutz) merged 3 commits into
microsoft:mainfrom
akshatshahh:fix/issue-3039-sequential-attack-child-ids
Oct 9, 2026
Merged

Roman Lutz (romanlutz) merged 3 commits into
microsoft:mainfrom
akshatshahh:fix/issue-3039-sequential-attack-child-ids

Conversation

@akshatshahh

Copy link
Copy Markdown
Contributor

Fixes #3039.

When a child of SequentialAttack raises, the child error result is persisted, but the orchestration parent's error result did not retain metadata["child_attack_result_ids"] — losing references to earlier children that completed before a later child failed, and to the failed child itself.

What changed

  • pyrit/executor/attack/core/attack_strategy.py — the generic strategy error path (_on_error_async) now:
    • records the persisted error result's attack_result_id on the exception, so a catching orchestrator can link the failed child's stored result;
    • merges extra error-result metadata a failing strategy attached to the exception, and consumes it so an outer orchestrator doesn't re-merge stale links.
  • pyrit/executor/core/strategy.py — when the execution wrapper re-raises as _StrategyRuntimeError, it propagates the persisted error-result id so orchestrators don't have to walk the cause chain.
  • pyrit/executor/attack/compound/sequential_attack.py — _perform_async catches a child failure, attaches the ids of children that produced stored results (completed children in dispatch order, plus the failed child's persisted error result id), and re-raises unchanged.
  • pyrit/exceptions/exception_context.py — the two exception-attribute constants, following the existing pattern of carrying failure context on the exception.

Per the issue's constraints: exception propagation is preserved (the child error still raises, verified by the tests), no thrown exception is turned into a returned error result, dispatch order is preserved, no ids are invented for children that never produced a stored result, and nested compounds link each level hierarchically.

Tests

New TestChildFailurePreservesLinks in tests/unit/executor/attack/compound/test_sequential_attack.py uses real strategies, the real AttackExecutor, and SQLite memory (no live targets):

  • parent error result links the completed child and the failed child's persisted error result, in dispatch order;
  • nested compounds link each envelope to its direct children;
  • Scenario-attributed execution keeps both the links and the attribution.

Verified fail-first (new tests fail on unmodified base), then 55/55 in the compound test file, 275 passed across executor core/compound + exceptions suites, ruff check and format clean. The 2 failed / 13 errored tests in tests/unit/executor/attack/streaming and multi_turn are pre-existing on the base (missing optional deps), unrelated to this change.

AI disclosure

This contribution was developed with AI assistance (Muse). I reviewed and tested all changes; the fix was verified fail-first with real SQLite-backed execution as described above.

When a child of SequentialAttack raises, the child error result is
persisted, but the orchestration parent's error result did not retain
metadata['child_attack_result_ids'], losing references to earlier
children that completed before a later child failed.

The generic strategy error path now records the persisted error result's
id on the exception and merges exception-attached metadata into the
error result (consumed so outer orchestrators don't re-merge stale
links). SequentialAttack attaches the ids of children that produced
stored results -- completed children in dispatch order plus the failed
child's persisted error result -- and re-raises unchanged, preserving
exception propagation, outcome semantics, and retry/resume behavior.

Fixes microsoft#3039
@akshatshahh

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

@romanlutz Roman Lutz (romanlutz) self-assigned this Oct 9, 2026
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@romanlutz Roman Lutz (romanlutz) changed the title fix(sequential-attack): preserve child-result links when execution fails FIX: preserve child-result links when execution fails in SequentialAttack Oct 9, 2026
Track confirmed result IDs in each attack context and return them with incomplete executor objectives. Keep compound failure metadata local to its execution, verify uncertain writes without retrying, and preserve original exceptions and nested child links.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@romanlutz
Roman Lutz (romanlutz) added this pull request to the merge queue Oct 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 9, 2026
@romanlutz
Roman Lutz (romanlutz) added this pull request to the merge queue Oct 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 9, 2026
@romanlutz
Roman Lutz (romanlutz) added this pull request to the merge queue Oct 9, 2026
Merged via the queue into microsoft:main with commit d249217 Oct 9, 2026
79 of 82 checks passed
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.

FIX Preserve SequentialAttack child-result links when execution fails

2 participants