[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [local‑first/Evolu](https://evolu.dev/docs/api-reference/common/local-first/Evolu) › forgetWrappedDeviceSecret

```ts
function forgetWrappedDeviceSecret<OnlyPending extends boolean = false>(
  appName: string & Brand<"UrlSafeString"> & Brand<"AppName">,
  __namedParameters?: {
    onlyPending?: OnlyPending;
  },
): Task<
  void,
  UnknownError | OnlyPending extends true
    ? WrappedDeviceSecretStoredError
    : never,
  CreateDbWorkerDep &
    CreateBroadcastChannelDep &
    CreateMessageChannelDep &
    DevicePersistenceDep &
    LockManagerDep &
    ReloadAppDep &
    Partial<ConsoleDep> &
    Partial<CreateMemoryInstanceWorkerDep> &
    Partial<FlushSyncDep> &
    Partial<RequestPersistentStorageDep> &
    StoredWorkerDep
>;
```

Defined in: [packages/common/src/local-first/Evolu.ts:3238](https://github.com/evoluhq/evolu/blob/aa223771feea747ffb1b0f5f3271574455633e37/packages/common/src/local-first/Evolu.ts#L3238)

Forgets the app's stored [WrappedDeviceSecret](https://evolu.dev/docs/api-reference/common/local-first/Auth/variables/WrappedDeviceSecret), or a setup's pending
key, so the next [unlockWrappedDeviceSecret](https://evolu.dev/docs/api-reference/common/local-first/Evolu/functions/unlockWrappedDeviceSecret) is a first use, with
another key and another [DeviceSecret](https://evolu.dev/docs/api-reference/common/local-first/Auth/variables/DeviceSecret). It's how an app starts over when
the key is gone for good, such as a deleted passkey, which the provider
reports like a dismissed prompt, or after a [DeviceSecretUnwrapError](https://evolu.dev/docs/api-reference/common/local-first/Auth/interfaces/DeviceSecretUnwrapError).
Evolu never calls it on its own.

A pending key wrapped no secret, so forgetting it loses nothing, and with
`onlyPending`, it forgets only that: when it finds a stored secret, it
forgets nothing and fails with [WrappedDeviceSecretStoredError](https://evolu.dev/docs/api-reference/common/local-first/Auth/interfaces/WrappedDeviceSecretStoredError). It
checks under the lock setups take, so a setup in another tab can't store a
secret between the check and the forget, as it can after
[hasWrappedDeviceSecret](https://evolu.dev/docs/api-reference/common/local-first/Evolu/functions/hasWrappedDeviceSecret). An app that offers to start over calls it with
`onlyPending` first, without a warning, and on that error asks the user to
confirm before calling it without `onlyPending`. Forgetting a stored secret
loses its device database: nothing opens it again, so its AppOwners return
only from their backups, and its device tables and the AppOwners' names are
gone. An AppOwner restored from its backup reopens its own database with its
local data, unsynced changes included. With
[EvoluAppConfig.createFirstAppOwner](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/EvoluAppConfig#createfirstappowner), the new device database creates a
new, empty AppOwner, so a user who restores one from a backup has two; after
the restore, remove the empty one with [EvoluApp.remove](https://evolu.dev/docs/api-reference/common/local-first/Evolu/interfaces/EvoluApp#remove).

A tab that is already unlocked stays on the old device database until it
reloads. AppOwners added there are lost at the next start, and it's the last
place where the user can still back up the old ones.

When it finds a pending key or a stored secret, it waits for a setup running
in another tab, but not for an unlock of a stored secret, whose prompt can
stay open. Where the platform keeps nothing, there's nothing to forget. When
its database is refused, as `evoluError` reports, it fails with an
[UnknownError](https://evolu.dev/docs/api-reference/common/Error/variables/UnknownError), the refusal itself or one wrapping it. Like
[createEvoluApp](https://evolu.dev/docs/api-reference/common/local-first/Evolu/functions/createEvoluApp), it stays pending while another build of the app keeps
it waiting or the shared worker fails to load.

### Example

```ts
import {
  AppName,
  assertEqual,
  forgetWrappedDeviceSecret,
  ok,
} from "@evolu/common";
import { createEvoluDeps, createRun } from "@evolu/web";

const run = createRun(createEvoluDeps());
const appName = AppName.orThrow("StartOver");

// After an unlock failed, without a warning.
const forgotten = await run(
  forgetWrappedDeviceSecret(appName, { onlyPending: true }),
);
if (
  !forgotten.ok &&
  forgotten.error.type === "WrappedDeviceSecretStoredError"
) {
  // Once the user confirms losing the device database.
  await run.orThrow(forgetWrappedDeviceSecret(appName));
}
// Nothing was stored, so there was nothing to forget.
assertEqual(forgotten, ok());
```

After a stored secret was forgotten:

```ts
import {
  AppName,
  assertEqual,
  assertOk,
  createDeviceSecret,
  createEvoluApp,
  createRandomBytes,
  id,
  mnemonicToOwnerSecret,
  NonEmptyTrimmedString100,
  testAppOwner,
} from "@evolu/common";
import { createEvoluDeps, createRun } from "@evolu/web";

const Schema = {
  todo: { id: id("Todo"), title: NonEmptyTrimmedString100 },
};
const run = createRun(createEvoluDeps());
// The DeviceSecret of the first unlock after forgetWrappedDeviceSecret.
const secret = createDeviceSecret({ randomBytes: createRandomBytes() });

await using app = await run.orThrow(
  createEvoluApp(Schema, {
    appName: AppName.orThrow("ForgetWrappedDeviceSecret"),
    auth: { type: "DeviceSecret", secret },
    createFirstAppOwner: true,
    transports: [],
  }),
);
// The new device database created an empty AppOwner.
const [empty] = app.appOwners.get();

// Restore the user's AppOwner from its backup, then remove the empty one.
assertOk(await app.add(mnemonicToOwnerSecret(testAppOwner.mnemonic)));
assertOk(await app.remove(empty.id));
assertEqual(
  app.appOwners.get().map(({ id }) => id),
  [testAppOwner.id],
);
```