---
title: Context
sidebar:
  icon: user
description: Attach per-request data such as the caller, then read it inside any procedure.
---

The type argument to `tacho<C>()` is the context shape. `handle()` puts `req` on context. Pass `createContext` to merge more.

```ts twoslash
import { tacho } from "tacho";
import { handle } from "tacho/transport/fetch";

const rpc = tacho<{ req: Request; user?: string }>();

export const router = rpc({
  me: rpc.run(({ ctx }) => ctx.user),
});

handle(router, {
  createContext: (req) => ({
    user: req.headers.get("x-user") ?? undefined,
  }),
});
```

Throw from `createContext` → JSON-RPC `INTERNAL_ERROR`.

Set context per call in middleware with `next({ ctx })`:

```ts twoslash
import { RpcError, tacho } from "tacho";

const rpc = tacho<{ req: Request; user?: string }>();

const withUser = rpc.use(async ({ ctx, next }) => {
  const user = ctx.req.headers.get("x-user");
  if (!user) {
    throw new RpcError({ code: -32001, message: "unauthorized" });
  }
  return next({ ctx: { user } });
});

export const router = rpc({
  me: withUser.run(({ ctx }) => ctx.user),
});
```
