# Apache Maka SessionStatus States and Blocked Session Handling Explained

> Explore Apache Maka's SessionStatus states active running waiting_for_user blocked and aborted. Learn how blocked sessions with typed blockedReason enable recovery and UI updates.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: deep-dive
- Published: 2026-09-02

---

**Apache Maka defines five `SessionStatus` states—`active`, `running`, `waiting_for_user`, `blocked`, and `aborted`—with blocked sessions recording a typed `blockedReason` that drives both recovery logic and UI presentation.**

The `SessionStatus` enum in Apache Maka forms the backbone of conversation lifecycle management. This open-source framework models user-driven AI sessions as state machines, where transitions between statuses trigger persistence updates, UI changes, and recovery workflows. Understanding these states—and specifically how the **`blocked`** state enables graceful error recovery—is essential for building resilient Maka applications.

## The Five SessionStatus States in Apache Maka

The canonical definition lives in [`packages/core/src/session.ts`](https://github.com/apache/maka/blob/main/packages/core/src/session.ts). The `SESSION_STATUSES` array and accompanying TypeScript types define five distinct phases:

- **`active`** — The session exists in storage but no Runtime Host has attached to it yet. This is the initial state after session creation.

- **`running`** — A live Runtime Host is actively executing the session. One or more conversation turns may be in flight, with the model generating responses or tools executing.

- **`waiting_for_user`** — The runtime has voluntarily paused because it requires additional input from the user. This commonly occurs when a permission request is pending or the workflow needs explicit confirmation.

- **`blocked`** — Execution has stopped due to a **recoverable error**. Unlike `aborted`, blocked sessions can be resumed once the underlying issue is resolved. This state carries a mandatory `blockedReason` field.

- **`aborted`** — The session has terminated permanently. This occurs when the user explicitly stops the session or an unrecoverable error prevents any further progress.

The `SessionStatus` type itself is defined as a union of these string literals, with runtime guards like `isSessionStatus()` available for type narrowing.

## SessionBlockedReason: Why Sessions Become Blocked

When a session enters the `blocked` state, Apache Maka records a specific **`SessionBlockedReason`** to enable targeted recovery. Also defined in [`packages/core/src/session.ts`](https://github.com/apache/maka/blob/main/packages/core/src/session.ts), the `SESSION_BLOCKED_REASONS` array contains five possible values:

| Blocked Reason | Recovery Action Required |
|----------------|--------------------------|
| `NO_REAL_CONNECTION` | Configure a usable model connection before resuming |
| `auth` | Re-authenticate the user (e.g., refresh expired credentials) |
| `permission_required` | User must grant a permission through the request UI |
| `tool_failed` | A tool call failed; user intervention needed to retry or modify parameters |
| `unknown` | Unexpected error occurred; session can be retried generically |

The `SessionBlockedReason` type is intentionally granular. This allows both automated recovery workflows and precise UI messaging without parsing error strings.

## How Blocked Session Handling Works in the Runtime

The transition to `blocked` status involves three coordinated components: projection helpers that build persistence patches, the session manager that applies updates, and storage layers that ensure durability.

### Building Status Patches with buildStatusPatch

In [`packages/runtime/src/session-projection-helpers.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/session-projection-helpers.ts), the `buildStatusPatch` function creates the partial update sent to durable storage:

```typescript
function buildStatusPatch(
  status: SessionStatus,
  ts: number,
  blockedReason?: SessionBlockedReason,
): Pick<SessionHeader, 'status' | 'blockedReason' | 'statusUpdatedAt'> {
  return {
    status,
    blockedReason: status === 'blocked' ? (blockedReason ?? 'unknown') : undefined,
    statusUpdatedAt: ts,
  };
}

```

This helper enforces a critical invariant: **`blockedReason` is only persisted when status equals `blocked`**. For any other status, the field is explicitly cleared to `undefined`, preventing stale reason data from confusing recovery logic.

### Mapping Errors to Blocked Reasons

The same file provides `blockedReasonFromErrorReason()`, which translates internal error strings into public `SessionBlockedReason` values:

```typescript
// Internal runtime error → user-facing blocked reason
const reason = blockedReasonFromErrorReason('permission_required');
// Returns: 'permission_required' (typed as SessionBlockedReason)

```

This indirection layer insulates the persistence schema from internal error naming conventions.

### SessionManager Persistence Flow

The `SessionManager` in [`packages/runtime/src/session-manager.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/session-manager.ts) orchestrates the actual status change. When the runtime encounters a recoverable failure, it calls `setSessionStatus()`:

```typescript
await setSessionStatus(sessionId, 'blocked', 'tool_failed');

```

Behind the scenes, this invokes `updateHeader(sessionId, buildStatusPatch(...))` to atomically persist the new `SessionHeader`. The storage layer in [`packages/storage/src/session-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/session-store.ts) applies the `isSessionBlockedReason` guard during serialization, ensuring type safety across the persistence boundary.

## Rendering Blocked Sessions in the UI

The presentation layer converts raw status data into user-facing elements. In [`packages/ui/src/session-status-presentation.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/session-status-presentation.ts), the `presentSessionStatus()` function accepts a `SessionStatus` and optional `blockedReason`, returning display primitives:

```typescript
import { presentSessionStatus } from '@maka/ui/session-status-presentation';

const { label, icon, variant, tone } = presentSessionStatus('blocked', 'permission_required', 'en');
// Returns localized label "Permission Required", warning variant, etc.

```

A companion file, [`conversation-copy.ts`](https://github.com/apache/maka/blob/main/conversation-copy.ts), provides message templates that incorporate the blocked reason into explanatory text. This separation between data (`SessionStatus`), reason (`SessionBlockedReason`), and presentation (`presentSessionStatus`) enables consistent UX across web, desktop, and CLI clients.

## Complete Code Examples

### Blocking a Session from Runtime Code

```typescript
import { setSessionStatus } from '@maka/runtime/session-manager';
import { SessionStatus, SessionBlockedReason } from '@maka/core/session';

async function handleConnectionFailure(sessionId: string) {
  const blockedReason: SessionBlockedReason = 'NO_REAL_CONNECTION';
  await setSessionStatus(sessionId, 'blocked', blockedReason);
}

```

### Reading Blocked Status from Storage

```typescript
import { getSessionHeader } from '@maka/storage/session-store';

async function checkSessionHealth(sessionId: string): Promise<boolean> {
  const header = await getSessionHeader(sessionId);
  
  if (header.status === 'blocked') {
    console.error(`Blocked: ${header.blockedReason}`);
    return false;
  }
  return header.status === 'running';
}

```

### React Component for Session Status Badge

```tsx
import { presentSessionStatus } from '@maka/ui/session-status-presentation';
import type { SessionSummary } from '@maka/core/session';

function SessionStatusBadge({ session }: { session: SessionSummary }) {
  const presentation = presentSessionStatus(
    session.status, 
    session.blockedReason,
    navigator.language
  );
  
  return (
    <span className={`badge badge-${presentation.variant}`}>
      {presentation.label}
    </span>
  );
}

```

## Key Source Files for SessionStatus Handling

| File | Responsibility |
|------|--------------|
| [`packages/core/src/session.ts`](https://github.com/apache/maka/blob/main/packages/core/src/session.ts) | Core type definitions: `SessionStatus`, `SessionBlockedReason`, `SessionHeader`, type guards |
| [`packages/runtime/src/session-projection-helpers.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/session-projection-helpers.ts) | `buildStatusPatch()`, `blockedReasonFromErrorReason()` for status transitions |
| [`packages/runtime/src/session-manager.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/session-manager.ts) | `setSessionStatus()`, `updateHeader()` for orchestrating persistence |
| [`packages/storage/src/session-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/session-store.ts) | SQLite persistence with `isSessionBlockedReason` validation |
| [`packages/ui/src/session-status-presentation.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/session-status-presentation.ts) | `presentSessionStatus()` for converting status to UI primitives |

## Summary

- Apache Maka defines **five session states** in [`packages/core/src/session.ts`](https://github.com/apache/maka/blob/main/packages/core/src/session.ts): `active`, `running`, `waiting_for_user`, `blocked`, and `aborted`.

- The **`blocked` state** is recoverable and always carries a `blockedReason` from the five possible values: `NO_REAL_CONNECTION`, `auth`, `permission_required`, `tool_failed`, or `unknown`.

- **Status transitions** use `buildStatusPatch()` in [`session-projection-helpers.ts`](https://github.com/apache/maka/blob/main/session-projection-helpers.ts) to enforce that `blockedReason` only persists alongside `blocked` status.

- **Error mapping** through `blockedReasonFromErrorReason()` decouples internal errors from the public schema.

- **Full lifecycle flow**: Runtime detects error → reason mapping → patch building → `SessionManager` persistence → `session-store` durability → UI presentation via `presentSessionStatus()`.

## Frequently Asked Questions

### What triggers a session to enter the blocked state?

A session becomes `blocked` when the runtime encounters a **recoverable error** that requires user action before execution can continue. Common triggers include: a tool call throwing an exception (`tool_failed`), the user needing to re-authenticate (`auth`), a missing model connection (`NO_REAL_CONNECTION`), or pending permission grants (`permission_required`). Unlike `aborted`, blocked sessions retain their conversation history and can be resumed.

### How does Apache Maka prevent stale blockedReason values in session storage?

The `buildStatusPatch()` helper in [`session-projection-helpers.ts`](https://github.com/apache/maka/blob/main/session-projection-helpers.ts) explicitly sets `blockedReason` to `undefined` whenever the status is not `'blocked'`. This ensures that transitioning from `blocked` to `running` or `active` automatically clears the reason field. The storage layer validates this through the `isSessionBlockedReason` guard when reading headers back from SQLite.

### Can I customize the UI messages shown for each blocked reason?

Yes, but through the presentation layer rather than core types. The `presentSessionStatus()` function in [`packages/ui/src/session-status-presentation.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/session-status-presentation.ts) maps each `SessionBlockedReason` to a label, icon variant, and tone. To customize messaging, you can wrap or replace this function while keeping the underlying `SessionBlockedReason` types unchanged—ensuring compatibility with the runtime's error handling logic.

### What is the difference between `waiting_for_user` and `blocked`?

`waiting_for_user` represents an **intentional pause** by the runtime, typically for permission requests that are part of normal workflow execution. The system expects the user to respond, but no error occurred. `blocked` represents an **unexpected or error condition** that stopped execution—while recoverable, it indicates something went wrong rather than proceeding as designed.