audit agent loop detected re-scanning the same broken modal
Fixes audit agent infinite loops on broken modals with state fingerprinting and a report-and-skip escape hatch. Use it when the agent re-scans the same dialog repeatedly. Not for modals the agent simply has not learned to dismiss yet.
audit agent loop detected re-scanning the same broken modal - how to fix it
TL;DR
Add loop detection with a visited-state fingerprint: hash the dialog's markup plus the agent's action history, and when the same state repeats three times, break out, report the modal as broken, and move on. One line of why: a modal that cannot be dismissed or audited will trap any agent that lacks a give-up condition.
The error, verbatim
AuditAgentError: loop detected, same modal state 8 times
dialog: .broken-modal (no close button, Escape ignored)
actions_tried: click overlay, press Escape, click [data-close]
Fix it step by step
Step 1: Reproduce the loop
node agent/run-audit.js --route /promo | rg -i 'loop|same state' | head -5Expected: The loop detector fires on the broken modal.
Step 2: Confirm the modal is genuinely broken
npx @axe-core/cli https://example.com/promo --rules aria-hidden-focus | tail -3Expected: A human check: the modal likely also fails keyboard dismissal, so it is a product bug.
Step 3: Add the give-up condition
rg -n 'loop|visited|fingerprint' agent/actions.js | head -10Expected: Add state fingerprinting with a repeat cap, then report-and-skip.
Step 4: Re-run the audit
node agent/run-audit.js --route /promo | tail -4Expected: Agent reports the broken modal once and completes the rest of the audit.
Step 5: Add a regression probe
node agent/run-audit.js --smoke | tail -3Expected: Smoke run passes; schedule it so the breakdown is caught if it ever regresses.
When to use this skill
- You run an agent that scans UIs for accessibility and it hits this breakdown
- The agent's scan loop stalls, crashes, or loops on this exact failure
- You are hardening an audit agent's error handling for production scans
When NOT to use this skill
- A human runs the scan manually and it works, this is agent-harness failure handling
- The scan completes and only reports violations, use the rule-specific skills
Compatibility
Audit agent harness with action history. The fingerprint is a hash of dialog markup plus recent actions. Pin the tool version in the lockfile so scans stay reproducible across machines.
Variant phrasings
agent loop on modal
Same trap, same give-up fix.
audit agent rescanning same dialog
Practitioner phrasing.
the breakdown hits other routes too
Agent failure modes are systemic; apply the hardening to every route the agent covers, not just the one that failed.
Why it happens
Some modals are genuinely broken: no close button, Escape ignored, overlay click disabled. An agent without loop detection retries its dismissal playbook forever, re-scanning the same dialog each time. The fix is a visited-state fingerprint (hash of the dialog's outer markup plus the last N actions) with a repeat threshold. Hitting the threshold is not an agent failure, it is a finding: the modal is broken, report it as such and continue the audit. Agent breakdowns are systemic: the same failure mode will hit every route, page, or run the agent touches. Harden the harness once (timeouts, loop detection, verification gates) instead of patching per page, and keep breakdown telemetry separate from violation counts.
Edge cases
- The repeat threshold should be low (3), a working dismissal succeeds on the first or second try.
- Report the broken modal as a finding with the tried actions, that is valuable audit output.
- Distinguish agent-loop (same actions, same state) from page-loop (page genuinely cycles), both need escape hatches.
- Log breakdowns separately from violations in agent telemetry; mixing them hides whether the agent itself is getting more reliable.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_3DJIrU98MeJw2sRVKJKgpQ
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.