# Guard is held across a disallowed await

Rule ID: concurrency.guard-held-across-suspension@1.0.0. Availability below refers to source-scan at product 524fa07e.

## V-ASYNC-14 — Guard is held across a disallowed await

Holding a synchronous guard across an await can violate its allowed suspension or thread-affinity contract and prevent other work from making progress.

### Availability

Selected by default in source-scan. Selection does not mean a supported observation exists in your program.

Use the terminal from [Installation](https://docs.swift-analyzer.com/get-started/installation/), with ANALYZER set. Replace `<package>` and `<product>` with your supported package path and product name.

```text
"$ANALYZER" source-scan --package-path <package> --product <product> --allow-build
```

### Example and action

Reproduced as part of the first-analysis package at product 524fa07e on Apple Swift 6.3.3, macOS arm64. Read the [complete example](https://docs.swift-analyzer.com/get-started/first-analysis/) before running it.

```swift
import Foundation
private let gate = NSLock()
private func enter() { gate.lock() }
private func leave() { gate.unlock() }
func perform() async { enter(); await Task.yield(); leave() }
```

The control releases the guard before suspension. In a real application, copy the necessary state under the guard and revalidate it before applying a later result. Moving release is not safe if the operation requires a stronger state protocol.

```swift
import Foundation
private let gate = NSLock()
private func enter() { gate.lock() }
private func leave() { gate.unlock() }
func perform() async { enter(); leave(); await Task.yield() }
```

### Why this check works

The check follows recognized guard acquisition, suspension and release events in an admitted trace. An acquired guard that survives the disallowed suspension supplies a witness. The tutorial produces one such finding and also an incomplete trace; both are preserved in the degraded report.

### Assumptions and unknown

The source mapper does not model every lock wrapper or synchronization primitive. Missing events, unclear guard identity or an incomplete trace preserve unknown. A witness in one trace does not establish completeness of another trace.

### Evidence and interpretation

Read condition coverage, observation counts and reasons in the actual report. A finding and an unknown observation can coexist. No observations is not a negative proof.

Historical evidence at 4558458d: recovery-required (historical qualification is incomplete and needs further evidence). That evidence has not been requalified for this product revision.

[How we validate checks](https://docs.swift-analyzer.com/concepts/validation/) explains the evidence boundary. [Foundations](https://docs.swift-analyzer.com/concepts/foundations/) separates method assumptions from implementation claims.


---

Language: en
Canonical: https://docs.swift-analyzer.com/catalog/concurrency.guard-held-across-suspension/
Product revision: 524fa07e0ae4153c84ac12ae9eb6559df89ec2be
Catalog revision: 4558458d
Documentation digest: 1f17ba58ab08627e0de898f1442067b09e960b48cd5605d6529e9275f8930d68
Channel: pre-prod; maturity: experimental; access: owner-provided checkout.
