---
title: "Await every async call · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/concurrency/await-every-promise
id: ARC-33
level: Required
risk: data
updated: 2026-10-22
build: a2a6bdfed830
tokens: 920
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Await every async call

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Concurrency](https://agentwranglers.se/playbook/architecture/concurrency.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: ARC-33
- Level: Required
- Chapter: [Concurrency](https://agentwranglers.se/playbook/architecture/concurrency.md)
- Rule: Await every promise, task or future, or hand it to code that handles its errors. A call that nobody waits for loses its errors without a trace.
- Check: A linter fails on unhandled async calls. Examples are typescript-eslint `no-floating-promises` and `no-misused-promises`, Ruff `RUF006` for asyncio tasks, and for C# the compiler warning `CS4014` plus the analyzer `VSTHRD100` against `async void`.
- Risk: Data leaked or lost
- How: Use one async style across the codebase, such as `async` and `await`, instead of mixing callbacks and promise chains. When work must run in the background, pass it to a queue or a task runner that logs failures. Handle each awaited error as [Never swallow errors](https://agentwranglers.se/playbook/architecture/errors-and-nulls/never-swallow-errors.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### TypeScript example

```ts
// Bad: if sending fails, nobody ever knows
function placeOrder(order: Order) {
  saveOrder(order);
  sendConfirmation(order);
}

// Good: errors reach the caller
async function placeOrder(order: Order) {
  await saveOrder(order);
  await sendConfirmation(order);
}
```

### Python example

```python
# Bad: the task runs on its own, and its error is lost
async def place_order(order):
    asyncio.create_task(send_confirmation(order))

# Good: errors reach the caller
async def place_order(order):
    await save_order(order)
    await send_confirmation(order)
```

### Plain text example

```csharp
// Bad: async void hides the failure
async void PlaceOrder(Order order) { await SaveOrder(order); }

// Good: return the Task, so the caller awaits it
async Task PlaceOrder(Order order) { await SaveOrder(order); }
```

## Sources

- [C# compiler warning CS4014](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/async-await-errors#async-practices)
- [Python asyncio.create_task](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)

## Related rules

- ARC-79 [Start tasks only inside a scope that waits for them](https://agentwranglers.se/playbook/architecture/concurrency/structured-concurrency.md) in Clean code and architecture
- ARC-31 [Never swallow errors](https://agentwranglers.se/playbook/architecture/errors-and-nulls/never-swallow-errors.md) in Clean code and architecture

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/architecture/concurrency/await-every-promise">Agent Wranglers clean code and architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Holding a lock while waiting on the network](https://agentwranglers.se/playbook/architecture/concurrency/no-lock-across-io.md)
- Next: [Guard state that concurrent code shares](https://agentwranglers.se/playbook/architecture/concurrency/guard-shared-state.md)
- [Concurrency](https://agentwranglers.se/playbook/architecture/concurrency.md)
