# AUR0771

## Error Message

`AUR0771: The aurelia instance must be fully stopped before it can be disposed`

## Description

This error occurs when the `aurelia.dispose()` method is called on an `Aurelia` instance that is still considered 'started' or 'running'. Before an Aurelia instance's container and associated resources can be disposed of, the application must be explicitly stopped using the `aurelia.stop()` method. The `stop()` method handles the graceful deactivation and detachment of the root component.

## Cause

The primary cause is calling `aurelia.dispose()` without first calling `await aurelia.stop()` (or handling the promise appropriately) on the same instance. Common scenarios include:

1. **Missing `stop()` call:** Forgetting to stop the application before attempting to dispose of it.
2. **Incorrect Order:** Calling `dispose()` immediately after `stop()` without waiting for the asynchronous `stop()` operation to complete.
3. **Calling `dispose()` on an instance that was never started:** While less common, attempting to dispose of an instance that hasn't successfully completed the `start()` and subsequent `stop()` sequence might lead to unexpected states, potentially triggering this error if internal state flags are inconsistent.

## Solution

1. **Call `stop()` Before `dispose()`:** Always ensure that `aurelia.stop()` is called and awaited (or its promise handled) before calling `aurelia.dispose()`.
2. **Await `stop()`:** Since `stop()` is asynchronous, use `await aurelia.stop()` or chain `dispose()` in the `.then()` callback of the promise returned by `stop()`.

## Example

```typescript
// main.ts (or relevant lifecycle management code)
import Aurelia from 'aurelia';
import { MyApp } from './my-app';

const host = document.querySelector('#app');

async function manageAppLifecycle() {
  const aurelia = new Aurelia();

  // Start the app
  await aurelia
    .app({ host, component: MyApp })
    .start();
  console.log('App started.');

  // ... application runs ...

  // Incorrect: Calling dispose() before stop()
  try {
    // aurelia.dispose(); // This would throw AUR0771
  } catch(e) {
    console.error("Incorrect dispose call:", e.message);
  }

  // Correct: Stop the app first, then dispose
  console.log('Stopping app...');
  await aurelia.stop(); // Wait for stop() to complete
  console.log('App stopped.');

  console.log('Disposing app instance...');
  aurelia.dispose(); // Now safe to call dispose()
  console.log('App disposed.');
}

manageAppLifecycle().catch(console.error);

// Example with .then()
const aureliaInstance = new Aurelia();
aureliaInstance.app({ host, component: MyApp })
  .start()
  .then(() => {
    console.log('App started (.then)');
    // ... run app ...
    console.log('Stopping app (.then)...');
    return aureliaInstance.stop(); // Return the promise from stop()
  })
  .then(() => {
    console.log('App stopped (.then).');
    console.log('Disposing app instance (.then)...');
    aureliaInstance.dispose(); // Safe to call dispose here
    console.log('App disposed (.then).');
  })
  .catch(err => console.error("Lifecycle error:", err));

```

## Debugging Tips

* Review the shutdown sequence of your Aurelia application.
* Ensure that `stop()` is called before `dispose()`.
* Verify that you are waiting for the `stop()` promise to resolve before proceeding to `dispose()`. Use `await` or `.then()`.
* Check if multiple parts of your code might be attempting to stop or dispose of the same Aurelia instance concurrently, leading to race conditions.
