> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/TanStack/query/llms.txt
> Use this file to discover all available pages before exploring further.

# createMutation

> Svelte function for performing mutations and side effects

Perform mutations and side effects with the `createMutation` function. It provides methods to trigger mutations and tracks their state reactively in Svelte 5.

## Signature

```ts theme={null}
function createMutation<TData, TError, TVariables, TContext>(
  options: Accessor<CreateMutationOptions<TData, TError, TVariables, TContext>>,
  queryClient?: Accessor<QueryClient>,
): CreateMutationResult<TData, TError, TVariables, TContext>
```

## Parameters

<ParamField path="options" type="Accessor<CreateMutationOptions<TData, TError, TVariables, TContext>>" required>
  A function (accessor) returning mutation configuration options.

  <Expandable title="properties">
    <ParamField path="mutationFn" type="(variables: TVariables) => Promise<TData>" required>
      The function that performs the mutation.
    </ParamField>

    <ParamField path="onMutate" type="(variables: TVariables) => Promise<TContext> | TContext">
      Called before mutation executes. Useful for optimistic updates. Return context value.
    </ParamField>

    <ParamField path="onSuccess" type="(data: TData, variables: TVariables, context: TContext) => void">
      Called when mutation succeeds.
    </ParamField>

    <ParamField path="onError" type="(error: TError, variables: TVariables, context: TContext | undefined) => void">
      Called when mutation fails.
    </ParamField>

    <ParamField path="onSettled" type="(data: TData | undefined, error: TError | null, variables: TVariables, context: TContext | undefined) => void">
      Called when mutation completes (success or error).
    </ParamField>

    <ParamField path="retry" type="number | boolean">
      Number of retry attempts or boolean to enable/disable retries.
    </ParamField>

    <ParamField path="retryDelay" type="number | ((attemptIndex: number) => number)">
      Delay between retry attempts.
    </ParamField>

    <ParamField path="throwOnError" type="boolean">
      Throw errors instead of setting error state.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="queryClient" type="Accessor<QueryClient>">
  Accessor returning a custom QueryClient instance. If not provided, uses the client from context.
</ParamField>

## Returns

<ResponseField name="CreateMutationResult<TData, TError, TVariables, TContext>" type="object">
  Reactive mutation state and methods.

  <Expandable title="properties">
    <ResponseField name="mutate" type="(variables: TVariables, options?: MutateOptions) => void">
      Trigger the mutation. Fire-and-forget style (doesn't return a promise).
    </ResponseField>

    <ResponseField name="mutateAsync" type="(variables: TVariables, options?: MutateOptions) => Promise<TData>">
      Trigger the mutation and return a promise.
    </ResponseField>

    <ResponseField name="data" type="TData | undefined">
      The mutation result data.
    </ResponseField>

    <ResponseField name="error" type="TError | null">
      The error object if the mutation failed.
    </ResponseField>

    <ResponseField name="isPending" type="boolean">
      `true` when the mutation is currently executing.
    </ResponseField>

    <ResponseField name="isSuccess" type="boolean">
      `true` when the mutation has succeeded.
    </ResponseField>

    <ResponseField name="isError" type="boolean">
      `true` when the mutation has failed.
    </ResponseField>

    <ResponseField name="isIdle" type="boolean">
      `true` when the mutation is idle (not executing).
    </ResponseField>

    <ResponseField name="status" type="'idle' | 'pending' | 'error' | 'success'">
      The current status of the mutation.
    </ResponseField>

    <ResponseField name="variables" type="TVariables | undefined">
      The variables passed to the mutation.
    </ResponseField>

    <ResponseField name="reset" type="() => void">
      Reset the mutation state to initial values.
    </ResponseField>
  </Expandable>
</ResponseField>

## Type Parameters

* `TData` - Type of data returned by the mutation
* `TError` - Type of error (defaults to `DefaultError`)
* `TVariables` - Type of variables passed to the mutation (defaults to `void`)
* `TContext` - Type of context returned by `onMutate` (defaults to `unknown`)

## Examples

### Basic Usage (Svelte 5 Runes)

```svelte theme={null}
<script lang="ts">
import { createMutation, useQueryClient } from '@tanstack/svelte-query'

const queryClient = useQueryClient()

const mutation = createMutation(() => ({
  mutationFn: async (newTodo) => {
    const res = await fetch('/api/todos', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(newTodo),
    })
    return res.json()
  },
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
}))

function handleCreate() {
  mutation.mutate({ title: 'New Todo', completed: false })
}
</script>

<button onclick={handleCreate} disabled={mutation.isPending}>
  {mutation.isPending ? 'Adding...' : 'Add Todo'}
</button>

{#if mutation.isError}
  <div>Error: {mutation.error?.message}</div>
{/if}
```

### With TypeScript

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

interface Todo {
  id: number
  title: string
  completed: boolean
}

interface CreateTodoVariables {
  title: string
  completed: boolean
}

const mutation = createMutation(() => ({
  mutationFn: async (variables: CreateTodoVariables): Promise<Todo> => {
    const res = await fetch('/api/todos', {
      method: 'POST',
      body: JSON.stringify(variables),
    })
    return res.json()
  },
}))

function handleCreate() {
  // Type-safe mutation call
  mutation.mutate({ title: 'Learn Svelte Query', completed: false })
}
</script>
```

### Optimistic Updates

```svelte theme={null}
<script lang="ts">
import { createMutation, useQueryClient } from '@tanstack/svelte-query'

const queryClient = useQueryClient()

const mutation = createMutation(() => ({
  mutationFn: updateTodo,
  onMutate: async (updatedTodo) => {
    // Cancel outgoing refetches
    await queryClient.cancelQueries({ queryKey: ['todos'] })
    
    // Snapshot previous value
    const previousTodos = queryClient.getQueryData(['todos'])
    
    // Optimistically update cache
    queryClient.setQueryData(['todos'], (old) => {
      return old.map(todo => 
        todo.id === updatedTodo.id ? updatedTodo : todo
      )
    })
    
    // Return context with snapshot
    return { previousTodos }
  },
  onError: (err, updatedTodo, context) => {
    // Rollback on error
    if (context?.previousTodos) {
      queryClient.setQueryData(['todos'], context.previousTodos)
    }
  },
  onSettled: () => {
    // Always refetch after error or success
    queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
}))
</script>
```

### Using mutateAsync

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

const mutation = createMutation(() => ({
  mutationFn: createTodo,
}))

async function handleSubmit() {
  try {
    const newTodo = await mutation.mutateAsync({ title: 'New Todo' })
    console.log('Created todo:', newTodo)
    // Navigate or show success message
  } catch (error) {
    console.error('Failed to create todo:', error)
  }
}
</script>

<button onclick={handleSubmit}>Submit</button>
```

### Per-Mutation Callbacks

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

const mutation = createMutation(() => ({
  mutationFn: createTodo,
}))

function handleCreate() {
  mutation.mutate(
    { title: 'New Todo' },
    {
      onSuccess: (data) => {
        console.log('Created:', data)
      },
      onError: (error) => {
        console.error('Failed:', error)
      },
    }
  )
}
</script>
```

### Reset Mutation State

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

const mutation = createMutation(() => ({
  mutationFn: createTodo,
}))

function handleCreate() {
  mutation.reset() // Reset previous state
  mutation.mutate({ title: 'New Todo' })
}
</script>

<button onclick={handleCreate}>Create</button>

{#if mutation.isSuccess}
  <div>Successfully created!</div>
{/if}
```

### Multiple Mutations

```svelte theme={null}
<script lang="ts">
import { createMutation, useQueryClient } from '@tanstack/svelte-query'

const queryClient = useQueryClient()

const createMutation = createMutation(() => ({
  mutationFn: createTodo,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
}))

const deleteMutation = createMutation(() => ({
  mutationFn: deleteTodo,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
}))
</script>

<button 
  onclick={() => createMutation.mutate({ title: 'New' })}
  disabled={createMutation.isPending}
>
  Create
</button>

<button 
  onclick={() => deleteMutation.mutate(1)}
  disabled={deleteMutation.isPending}
>
  Delete
</button>
```

### Error Handling with Retry

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

const mutation = createMutation(() => ({
  mutationFn: createTodo,
  retry: 3,
  retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
  onError: (error) => {
    console.error('Mutation failed after retries:', error)
  },
}))
</script>
```

### Reactive Mutation Options

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

let shouldRetry = $state(true)

const mutation = createMutation(() => ({
  mutationFn: createTodo,
  retry: shouldRetry ? 3 : 0,
}))
</script>

<label>
  <input type="checkbox" bind:checked={shouldRetry} />
  Enable retry
</label>
```

### Form Handling

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

let title = $state('')

const mutation = createMutation(() => ({
  mutationFn: createTodo,
  onSuccess: () => {
    title = '' // Clear form on success
  },
}))

function handleSubmit(e: Event) {
  e.preventDefault()
  mutation.mutate({ title, completed: false })
}
</script>

<form onsubmit={handleSubmit}>
  <input 
    type="text" 
    bind:value={title} 
    placeholder="Todo title"
    disabled={mutation.isPending}
  />
  <button type="submit" disabled={mutation.isPending}>
    {mutation.isPending ? 'Adding...' : 'Add Todo'}
  </button>
</form>

{#if mutation.isError}
  <p class="error">{mutation.error?.message}</p>
{/if}

{#if mutation.isSuccess}
  <p class="success">Todo added successfully!</p>
{/if}
```

### Loading States

```svelte theme={null}
<script lang="ts">
import { createMutation } from '@tanstack/svelte-query'

const mutation = createMutation(() => ({
  mutationFn: createTodo,
}))
</script>

<button onclick={() => mutation.mutate({ title: 'New' })}>
  Create Todo
</button>

{#if mutation.isPending}
  <div>Creating...</div>
{:else if mutation.isError}
  <div>Error: {mutation.error?.message}</div>
{:else if mutation.isSuccess}
  <div>Todo created successfully!</div>
{/if}
```

## Notes

<Note>
  Svelte Query uses Svelte 5's runes mode. The options parameter must be an accessor (function).
</Note>

<Tip>
  Use `mutate` for fire-and-forget operations and `mutateAsync` when you need to await the result or handle errors with try/catch.
</Tip>

<Warning>
  Always invalidate or update relevant queries after a successful mutation to keep your UI in sync with the server state.
</Warning>

## Related

* [createQuery](/api/svelte/create-query) - For fetching data
* [Mutations Guide](/concepts/mutations) - Detailed guide on mutations
