> ## Documentation Index
> Fetch the complete documentation index at: https://developer.suki.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# sessionAlreadyExists Remote Session Conflict

> Clear a blocking ambient session when create fails with sessionAlreadyExists and HTTP 409

`session.create()` fails with reason `sessionAlreadyExists` (HTTP **409**) when another Suki product already has an active ambient session for the same provider and EMR encounter. This applies to **Ambient interoperability** in the Headless Web SDK. Dictation and Form filling do not support interoperability.

<Warning>
  Use **`@suki-sdk/platform`** and **`@suki-sdk/platform-react`** **v0.3.0** or later. Pass **`emrEncounterId`** on create so the note is interoperable.
</Warning>

## Common causes

* A clinician started ambient on Web SDK, Mobile SDK, or another client for the same `emrEncounterId`.
* A previous session was left open instead of ended or canceled.
* Your UI retries `create` without clearing the remote session first.

## Fix

<Steps>
  <Step title="Catch sessionAlreadyExists">
    When `session.create()` fails, check whether `reason === "sessionAlreadyExists"`. The HTTP status is **409**.
  </Step>

  <Step title="Read blockingSessionId">
    Read `blockingSessionId` from `error.additionalProperties`. Some JSDoc comments say `metadata`. The runtime field is `additionalProperties`.
  </Step>

  <Step title="Clear the Remote Session">
    Call **`cancelRemote`** to discard the blocking session without generating a note, or **`endRemote`** so any audio already captured can be processed. Pass `{ ambientSessionId: blockingSessionId }` on `useAmbient` or `useAmbientSession`.
  </Step>

  <Step title="Retry Create">
    After the remote call succeeds, retry `session.create()` with the same `emrEncounterId` and `encounterId`. Headless Web SDK does not require a delay between a successful remote clear and the retry.
  </Step>
</Steps>

<Note>
  The `sessionAlreadyExists` conflict applies only when `session.create()` runs online. If the first ambient session is fully offline, another Suki product can start a session for the same EMR encounter without receiving a conflict error.
</Note>

```tsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
import { useAmbient } from "@suki-sdk/platform-react";

export function CreateOrResolveConflict() {
  const { cancelRemote, endRemote, session } = useAmbient();

  // Reuse the same encounterId for every re-ambient session on this note.
  const existingEncounterId = "visit-note-1";
  const emrEncounterId = "6ec3920f-b0b1-499d-a4e9-889bf788e5ab";

  const createOrResolveConflict = async () => {
    try {
      await session.create({
        encounterId: existingEncounterId,
        emrEncounterId,
      });
    } catch (error) {
      if (
        error &&
        typeof error === "object" &&
        "reason" in error &&
        error.reason === "sessionAlreadyExists"
      ) {
        const blockingSessionId =
          "additionalProperties" in error &&
          error.additionalProperties &&
          typeof error.additionalProperties === "object" &&
          "blockingSessionId" in error.additionalProperties
            ? String(error.additionalProperties.blockingSessionId)
            : undefined;

        if (!blockingSessionId) {
          throw error;
        }

        // Discard the blocking session:
        await cancelRemote({ ambientSessionId: blockingSessionId });

        // Or end the blocking session so captured audio can be processed:
        // await endRemote({ ambientSessionId: blockingSessionId });

        await session.create({
          encounterId: existingEncounterId,
          emrEncounterId,
        });
        return;
      }

      throw error;
    }
  };

  return (
    <button type="button" onClick={() => void createOrResolveConflict()}>
      Create or resolve conflict
    </button>
  );
}
```

<Warning>
  Use **`cancelRemote`** when you want to discard the blocking session. Use **`endRemote`** when you want the blocking session to end and process any audio already captured. If `cancelRemote` fails, the error reason is **`cancelRemoteSessionFailed`**. If `endRemote` fails, the error reason is **`endRemoteSessionFailed`**.
</Warning>

## Mobile SDK

On Mobile SDK, a similar interop conflict is **`remoteSessionConflict(blockingSessionId:)`**: another client holds an active session for the encounter. Use `blockingSessionId` with `cancelRemoteAmbientSession` or `endSessionRemotely`, then retry create. See [Mobile SDK error messages](/mobile-sdk/error-messages) and [Create ambient session](/mobile-sdk/ambient-guides/create-session).

## Next steps

<Icon icon="file-lines" iconType="solid" /> **[Resolve a remote session conflict](/documentation/cookbooks/resolve-session-conflict)** - End the remote session, then retry create

<Icon icon="file-lines" iconType="solid" /> **[session\_in\_progress on Partner API create](/documentation/troubleshooting/session-in-progress)** - HTTP 409 concurrent create on Partner APIs

<Icon icon="file-lines" iconType="solid" /> **[Create ambient session](/headless-web-sdk/guides/hooks/ambient-hook)** - `useAmbient`, including `cancelRemote` and `endRemote`

<Icon icon="file-lines" iconType="solid" /> **[Manage ambient session](/headless-web-sdk/guides/hooks/ambient-session-hook)** - `onSessionTerminatedByPeer` when another product ends the live session

<Icon icon="file-lines" iconType="solid" /> **[Empty notes after end session](/documentation/troubleshooting/empty-notes-after-end-session)** - Poll status before retrieving content
