Skip to content
AI.info

AI agents

Deadlocks, Cascading Errors, and Conflict Resolution

Detect and recover from cyclic dependencies, duplicated authority, error propagation, and incompatible agent goals.

By the end you can

Key idea

92% of catastrophic failures came from errors the software had already reported

A worker marked complete may cause the supervisor and downstream agents to skip their own checks. One local error becomes shared certainty. How often that conversion is the whole story has been counted, in the distributed data-intensive systems that came before agents.

The count comes from 198 randomly sampled user-reported failures across Cassandra, HBase, HDFS, Hadoop MapReduce and Redis. Of the 198, 48 were catastrophic. Ding Yuan and seven colleagues published the result in 2014, and one finding states the outcome: “Almost all catastrophic failures (92%) are the result of incorrect handling of non-fatal errors explicitly signaled in software.” Not errors nobody saw. Errors the software had already raised, and something downstream then handled wrongly.

The rest of the finding is the part that should change your design review. 58% of those catastrophic failures could have been detected by simple testing of the error-handling code. In 35% the error-handling fault was trivial: an empty handler or one that only logged, an abort on an over-caught exception, or a “FIXME”/“TODO” comment sitting where the recovery should have been. The failure path is the path nobody exercises. That is true in a database cluster and in an agent graph alike.

Propagate evidence and uncertainty, not only completion status, and place validation at critical joins.

Completion status travels faster than the evidence behind it, and every check downstream is skipped on its word.

Example

Three redundant Enactors, one state none of them could repair

On 19 October 2025 at 11:48 PM PDT, the Northern Virginia (US-EAST-1) Region of Amazon Web Services began a disruption. It did not end until 2:20 PM PDT the following day. The post-event summary traces the trigger to a latent race condition between two of the three redundant DynamoDB DNS Enactors. One Enactor had been delayed. When it ran, it applied a much older plan over the newer one, because its own staleness check had itself gone stale. The second Enactor's clean-up then deleted that plan. Every IP address for dynamodb.us-east-1.amazonaws.com was removed. Two automated components, each doing the job it was written to do, and nothing in the system owning the conflict between them.

What happened next is why this belongs in a lesson on coordination rather than one on DNS. “Additionally, because the active plan was deleted, the system was left in an inconsistent state that prevented subsequent plan updates from being applied by any DNS Enactors. This situation ultimately required manual operator intervention to correct.” — Amazon Web Services. The redundancy was real. There were three Enactors. None of the three could undo what two of them had done together. The repair path led out of the automated system entirely.

  • Decision at stake: whether any component owns the conflict between two agents that are each individually correct. Three Enactors were redundant with one another; redundancy distributes work, not authority over a disagreement.
  • Hidden assumption: more agents reduce cascading risk because responsibility is distributed. Here three redundant Enactors produced a state that no Enactor could act on, and the assumption inverted.
  • Primary control question: can any agent inside the system return it to a good state, or does recovery require leaving the system? On 20 October 2025 the documented answer was manual operator intervention.
  • Evidence to collect: the empty record itself. Every IP address for dynamodb.us-east-1.amazonaws.com disappearing at once is a detectable condition, and the stretch from 11:48 PM PDT to 2:20 PM PDT is what it costs when the detection is a human noticing.

Coordination errors masquerade as individual reasoning failures

Multi-agent systems can deadlock, livelock, duplicate work, overwrite state, or propagate one incorrect artifact through many downstream agents. That list is no longer a practitioner's intuition. It is a taxonomy built from annotated evidence, published in 2025 and presented at NeurIPS. The method is stated in the abstract: “We develop MAST through rigorous analysis of 150 traces, guided closely by expert human annotators and validated by high inter-annotator agreement (kappa = 0.88). This process identifies 14 unique modes, clustered into 3 categories: (i) system design issues, (ii) inter-agent misalignment, and (iii) task verification.” — Cemri and twelve co-authors.

Alongside the first Multi-Agent System Failure Taxonomy they released MAST-Data: 1,600+ annotated traces collected across 7 popular multi-agent frameworks. Read the three categories again and notice where two of them live. Not inside a model's reasoning. In how the system was designed, and in whether anyone checked the work.

The habit of reading a coordination fault as an individual one is much older than agents, and its most studied instance cost lives. Six massive radiation overdoses were delivered by the Therac-25 between June 1985 and January 1987. The mechanism was concurrency, not reasoning. The software allowed concurrent access to shared memory with no real synchronisation and used non-atomic test-and-set on shared variables. Race conditions between the treatment task and the keyboard handler played an important part in the accidents. For a long stretch the fault was located anywhere but there. The manufacturer wrote to the Yakima hospital that the damage “could not have been produced by any malfunction of the Therac-25 or by any operator error.” The investigation published in IEEE Computer in 1993 reached the conclusion to carry into any dependency graph: “Most accidents are system accidents; that is, they stem from complex interactions between various components and activities. To attribute a single cause to an accident is usually a serious mistake.” — Leveson and Turner.

Conflict resolution therefore requires explicit priorities, ownership, timeout policy, evidence standards, and a mechanism to pause the system when goals cannot be reconciled. None of those five live in a prompt.

Diagnose a stuck system by reading the agent and you will tune prompts for a fault that lives in the dependency graph.

Case

100 failing queries a second become 300

Retries compound, and the arithmetic needs no metaphor. Google's SRE book works the example: “100 QPS of retries in the first second leads to 200 QPS, then to 300 QPS, and so on”. Chapter 22 defines what that is: “A cascading failure is a failure that grows over time as a result of positive feedback”. Nothing in that sequence requires a bad decision by any component. Each retry is the correct local behaviour of a client that received an error. The sum of correct local behaviours is the outage.

Microsoft's guidance describes the same dynamic from the other end of the call: “If a service is busy, failure in one part of the system might lead to cascading failures”. An agent graph reproduces the pattern with more expensive units. Where a retry loop resends a query, a supervisor re-dispatches a task to a model. The amplification is measured in tokens and minutes rather than in QPS.

Case

Closed, open, half-open

The answer to that growth is a component that stops asking. Microsoft's guidance sets out the Circuit Breaker pattern as a state machine — “You can implement the proxy as a state machine that includes the following states” — and names three: Closed, Open and Half-Open. The purpose is stated plainly: “The Circuit Breaker pattern helps prevent an application from repeatedly trying to run an operation that's likely to fail”. It is explicitly not a retry policy: “This pattern avoids the retry-on-error approach, which can lead to excessive resource usage during dependency recovery and can overload performance on a dependency that's attempting recovery”.

The trip is a threshold, and what follows it is a trial. “Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all”, writes Martin Fowler. Then: “There is now a third state present - half open - meaning the circuit is ready to make a real call as trial to see if the problem is fixed”. The half-open state is the part worth transplanting into agent orchestration. Recovery is tested by one cheap probe with a defined verdict, not by releasing the full queue at a dependency that has just come back.

Visual

Wait-for graph and ownership map locate the stall

A stuck system is diagnosed from the Wait-for graph, the Ownership map, the Health signal, and the Conflict rule. The Conflict rule and Containment should each keep their own owner and their own test.

Two of these views are not aspirational. They ship with documented defaults, in databases most teams already run. PostgreSQL 17 does not check for a cycle on every blocked lock, because the check is expensive. It waits first. The documentation describes deadlock_timeout as “This is the amount of time to wait on a lock before checking to see if there is a deadlock condition”, and sets the value: “The default is one second (1s)”. That is the whole design in one parameter. Waiting is normal. Waiting past a threshold is a question, and the question is asked of the graph rather than of the waiter.

The Conflict rule needs a verdict as well as a detector. MySQL 8.4's InnoDB supplies one: “When deadlock detection is enabled (the default), InnoDB automatically detects transaction deadlocks and rolls back a transaction or transactions to break the deadlock.” The victim is chosen deterministically rather than argued about, by preferring small transactions as measured by the rows inserted, updated or deleted. Detection itself can be turned off through innodb_deadlock_detect. Copy the shape: a threshold before you look, a graph to look at, a deterministic tie-break, and an owner of the abort.

FigureProcess · 5 steps
  1. 1

    Wait-for graph

    Tracks which agent or task depends on which unresolved event.

  2. 2

    Ownership map

    Defines who may decide, mutate, approve, or cancel.

  3. 3

    Health signal

    Measures progress, heartbeat, queue age, and repeated messages.

  4. 4

    Conflict rule

    Priorities, evidence, human authority, or deterministic tie-breaks.

  5. 5

    Containment

    Stops propagation, revokes authority, and preserves evidence.

Comparison

The main choices inside multi-agent failure containment

Deadlock, Livelock, and Cascade look different from outside. One stops, one spins, one spreads. All three are cheapest to handle before the run burns through its budget, which is why the detection bar is that deadlocks and livelocks are detected before budgets are exhausted.

Livelock is the one teams argue about, so take a dated instance. DynamoDB recovered at 2:25 AM PDT on 20 October 2025, and EC2's DropletWorkflow Manager (DWFM) began re-establishing droplet leases. The work could not complete before the leases timed out, and further attempts queued behind the work already failing. DWFM was fully busy and going nowhere: “At this point, DWFM had entered a state of congestive collapse and was unable to make forward progress in recovering droplet leases.” — Amazon Web Services. A heartbeat would have reported DWFM alive for every minute of it. Only a progress metric separates that state from health: leases actually re-established, not attempts made. What ended it was less work rather than more capacity. Engineers throttled incoming work and began selective host restarts at 4:14 AM, and all leases in the Region were re-established by 5:28 AM.

A cascade is the harder case. It keeps making progress while the error spreads, because each agent accepts the label the one upstream attached instead of checking it.

FigureComparison · 3 columns

Deadlock

Agents wait on a cycle of dependencies that cannot resolve.

  • No progress
  • Stable waiting state
  • Needs cycle detection

Livelock

Agents keep acting or messaging without changing task state.

  • Consumes budget
  • Appears active
  • Needs progress metrics

Cascade

One bad artifact or decision propagates through dependent agents.

  • Fast amplification
  • Hard root-cause localization
  • Needs provenance

Steps

Run a coordination failure drill

Cycles and cascades are cheap to cause deliberately and expensive to meet by surprise. Drill them on a real workflow. Feed one agent a confidently mislabeled input and watch how far it travels. Error correlation grows when agents trust upstream labels instead of evidence, and a drill is what makes that visible.

The drill is not an improvisation you have to justify from first principles. It is a named discipline with a stated method. Netflix's Traffic and Chaos Team defined it in IEEE Software in 2016: “Chaos Engineering is the discipline of experimenting on a distributed system in order to build confidence in its capability to withstand turbulent conditions in production.” — Basiri and six colleagues. They set out four principles for designing the experiments: build a hypothesis around steady state behavior, vary real-world events, run experiments in production, automate experiments to run continuously. The first is the one most agent teams skip. Without a written statement of what steady state looks like, the drill produces anecdotes instead of a verdict.

Their reason for injecting error conditions rather than happy-path inputs is the finding already in this lesson, which they cite in their own paper: “A recent study reported that 92% of catastrophic system failures were the result of incorrect handling of non-fatal errors”. Then write down what your run showed about detection: how much budget was left when the cycle was caught, and whether anything caught it at all.

FigureProcess · 5 steps
  1. 1

    Create dependency cycles

    Simulate mutual approvals, missing owners, and blocked resources.

  2. 2

    Inject bad artifacts

    Observe whether downstream agents validate or blindly reuse them.

  3. 3

    Force concurrent writes

    Test version conflicts, duplicate side effects, and merge policy.

  4. 4

    Trigger timeouts

    Verify escalation, cancellation, and cleanup of abandoned work.

  5. 5

    Review containment

    Ensure credentials, queues, and pending actions are safely closed.

Containment works only if budget remains when you catch it

Treat coordination failures as first-class incidents. They require graph, state, and ownership observability beyond model traces. On-call engineers usually meet the cascade before they meet its cause: a stream of wrong answers that all trace back to one bad label nobody rechecked.

The cost of learning this late is on the record. On 1 August 2012 a repurposed flag at Knight Capital Americas activated years-dead “Power Peg” code that had been left on one of eight SMARS servers. 212 incoming parent orders produced over 4 million executions in 154 stocks, for more than 397 million shares, in about 45 minutes. The loss was over $460 million. The SEC's order of 16 October 2013 sets out what happened. The system had said so in advance: 97 automated “BNET reject” e-mails naming the fault were sent before the 9:30 a.m. open. They were not designed as alerts and were generally not reviewed. Machine evidence with no owner is not detection.

Then the containment attempt made it worse. “In one of its attempts to address the problem, Knight uninstalled the new RLP code from the seven servers where it had been deployed correctly. This action worsened the problem, causing additional incoming parent orders to activate the Power Peg code that was present on those servers, similar to what had already occurred on the eighth server.” A rollback is an action taken under time pressure by people reading incomplete state. It can widen the blast radius as easily as close it. The Commission imposed a $12,000,000 civil penalty.

Containment is working when the failure is caught while there is still budget left, when the containment action itself has been rehearsed against the dependency graph, and when the observability views are enough to say which agent stalled, which pair are waiting on each other, and where the bad label entered.

Model traces will show you a healthy agent sitting inside a system that has been stuck for hours.

Key takeaways