# Troubleshooting Common PI Desktop Errors: A Complete Guide to Result Types and Error Codes

> Troubleshoot common PI Desktop errors with our guide. Learn about Result types and error codes for network, tool, permission, and plugin failures to implement consistent retry logic and user messaging.

- Repository: [Lan/PI-Desktop](https://github.com/vastsa/PI-Desktop)
- Tags: how-to-guide
- Published: 2026-09-12

---

**PI Desktop uses a unified `Result<T>` discriminated union and `AppError` type to standardize error handling across network, tool, permission, and plugin failures, enabling consistent retry logic and user messaging.**

PI Desktop (vastsa/PI-Desktop) implements a robust error-handling architecture that replaces thrown exceptions with structured result types. Instead of crashing or returning ambiguous null values, every public API returns a `Result` object containing either success data or detailed error metadata. This pattern ensures that UI layers, extension developers, and internal agents handle failures in a predictable, type-safe manner.

## Core Error Architecture in PI Desktop

### The AppError Type and Result Pattern

At the heart of PI Desktop’s error system lies the `AppError` type defined in [`packages/shared/src/errors.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/errors.ts). This interface encapsulates everything needed to diagnose and recover from failures:

- **`code`**: A string identifier from the central `ErrorCodes` enum (e.g., `NETWORK_ERROR`, `TOOL_DENIED`)
- **`message`**: A human-readable description suitable for UI display
- **`details`**: Optional structured data containing HTTP status codes, stack traces, or underlying exception information
- **`retriable`**: A boolean flag indicating whether the operation can safely be retried
- **`traceId`**: A unique identifier for correlating errors across distributed logs

The `Result<T>` type is a discriminated union representing either success or failure:

```typescript
type Result<T> = 
  | { ok: true; data: T }
  | { ok: false; error: AppError };

```

According to the vastsa/PI-Desktop source code, this pattern forces consumers to explicitly handle both branches, eliminating undefined behavior from unhandled exceptions.

### The ErrorCodes Enum

All error identifiers are centralized in the `ErrorCodes` enum within [`packages/shared/src/errors.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/errors.ts). This registry includes exhaustive codes covering network providers, tool execution, permissions, plans, plugins, and host-core failures. By standardizing codes, the codebase ensures that a `NETWORK_ERROR` returned from [`agent-sidecar.ts`](https://github.com/vastsa/PI-Desktop/blob/main/agent-sidecar.ts) triggers the same UI behavior as one returned from a plugin.

## Common PI Desktop Error Categories

### Network and Provider Failures

Network errors occur when PI Desktop cannot reach external model providers such as OpenAI, Anthropic, or Ollama. Common codes include `NETWORK_ERROR`, `PROVIDER_ERROR`, `PROVIDER_RATE_LIMITED`, and `PROVIDER_UNAUTHORIZED`. These errors typically originate in [`apps/desktop/electron/main/agent-sidecar.ts`](https://github.com/vastsa/PI-Desktop/blob/main/apps/desktop/electron/main/agent-sidecar.ts) when HTTP requests fail or return non-2xx status codes. When encountering these errors, check the `details` property for the specific HTTP status and URL.

### Tool and Skill Execution Errors

Agent-side tools—such as filesystem operations or shell commands—emit errors like `TOOL_NOT_FOUND`, `TOOL_DENIED`, `TOOL_TIMEOUT`, `TOOL_FAILED`, and `TOOL_ABORTED`. These surface when a user blocks a privileged action or when a tool crashes during execution. The UI displays these as red badges in the tool panel, while logs contain the full `AppError` object with diagnostic context.

### Permission and Access Control Errors

Permission errors prevent unauthorized actions through codes like `PERMISSION_REQUIRED`, `PLUGIN_PERMISSION_DENIED`, and `WORKSPACE_PATH_DENIED`. Unlike other error types, these often trigger interactive prompts asking the user to approve the action. If the user ignores or rejects the prompt, the system returns a `PERMISSION_REQUIRED` error with `retriable` set to true, allowing the UI to re-prompt later.

### Plan and Goal Execution Errors

Plan-mode operations fail with codes such as `PLAN_APPROVAL_TIMEOUT`, `PLAN_EXECUTION_FAILED`, and `PLAN_INVALID_ACTION`. As implemented in [`apps/desktop/electron/main/plan-execution.ts`](https://github.com/vastsa/PI-Desktop/blob/main/apps/desktop/electron/main/plan-execution.ts), these errors occur when users do not approve a generated plan within the timeout window or when the execution engine cannot perform a planned action. The Plan UI panel displays yellow warning indicators containing the `AppError` message.

### Plugin and MCP Integration Errors

Plugin lifecycle failures use codes including `PLUGIN_INVALID`, `PLUGIN_LOAD_FAILED`, and `MCP_INVALID`. Generated in [`apps/desktop/electron/main/plugin-runtime.ts`](https://github.com/vastsa/PI-Desktop/blob/main/apps/desktop/electron/main/plugin-runtime.ts), these errors indicate corrupted plugin manifests, missing dependencies, or Model-Context-Protocol (MCP) server communication failures. The Plugin Marketplace UI surfaces these failures while detailed logs are written to the main process output.

### Host-Core and Internal Errors

Rust host process issues emit codes like `HOST_UNAVAILABLE`, `HOST_OVERLOADED`, `HOST_SHUTTING_DOWN`, `SESSION_NOT_FOUND`, `INTERNAL`, and `APP_DEGRADED`. These indicate SQLite corruption, missing sessions, or resource exhaustion in the Electron main process. When the host encounters these states, it writes to the application log and notifies the renderer process to display degradation warnings.

## Handling PI Desktop Errors Programmatically

To work with PI Desktop’s error system, import the `ok` and `err` constructors from [`packages/shared/src/errors.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/errors.ts):

```typescript
import { err, ok, Result } from "./errors.js";

// Wrapping a model provider call
async function fetchCompletion(prompt: string): Promise<Result<string>> {
  try {
    const response = await fetch("https://api.provider.com/v1/chat", {
      method: "POST",
      body: JSON.stringify({ prompt })
    });
    
    if (!response.ok) {
      // Return a structured error instead of throwing
      return err(
        "NETWORK_ERROR",
        `Provider returned status ${response.status}`,
        { status: response.status, url: response.url },
        true // retriable
      );
    }
    
    const data = await response.json();
    return ok(data.text);
  } catch (e) {
    return err(
      "INTERNAL",
      "Unexpected exception during fetch",
      { exception: e.message },
      false
    );
  }
}

```

When consuming a `Result`, always check the `ok` flag before accessing data:

```typescript
const result = await fetchCompletion("Explain monads");

if (!result.ok) {
  console.error(`Error ${result.error.code}: ${result.error.message}`);
  
  if (result.error.retriable) {
    // Implement exponential backoff retry logic
    setTimeout(() => fetchCompletion("Explain monads"), 1000);
  }
} else {
  console.log("Success:", result.data);
}

```

## RACP Error Mapping for Remote Agents

PI Desktop includes the Remote Agent Control Protocol (RACP) for communicating with external agent processes. Located in [`packages/shared/src/racp.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/racp.ts), this module ensures that errors crossing process boundaries remain interpretable.

The `toRacpErrorCode` function translates local error codes to remote protocol equivalents:

```typescript
import { toRacpErrorCode } from "./racp.js";

const remoteCode = toRacpErrorCode("PERMISSION_TIMEOUT");
// Returns: "APPROVAL_EXPIRED"

```

The `racpErrorIsRegistered` helper verifies that a received remote code maps to a known `ErrorCodes` value, preventing unknown error propagation:

```typescript
import { racpErrorIsRegistered, RACP_ERROR_CODES } from "./racp.js";

if (!racpErrorIsRegistered(remoteCode)) {
  console.warn("Received unregistered remote error code");
}

```

This mapping layer ensures that a `TOOL_DENIED` error generated locally produces the same user-facing behavior as a remotely-generated equivalent received via RACP.

## Summary

- PI Desktop returns `Result<T>` objects instead of throwing exceptions, forcing explicit error handling through the `ok` discriminant.
- The `AppError` type provides standardized fields: `code`, `message`, `details`, `retriable`, and `traceId`.
- All error codes are centralized in the `ErrorCodes` enum within [`packages/shared/src/errors.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/errors.ts).
- Remote agent errors are normalized via the RACP protocol in [`packages/shared/src/racp.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/racp.ts) using `toRacpErrorCode()` and `racpErrorIsRegistered()`.
- Always check `result.ok` before accessing `result.data`, and respect the `error.retriable` flag when implementing recovery logic.

## Frequently Asked Questions

### What is the Result type in PI Desktop?

The `Result<T>` type is a discriminated union defined in [`packages/shared/src/errors.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/errors.ts) that represents either a successful value (`{ ok: true, data: T }`) or a failure (`{ ok: false, error: AppError }`). This pattern eliminates null pointer exceptions and forces developers to handle error cases explicitly at the type level.

### How do I check if a PI Desktop error is retryable?

Inspect the `retriable` boolean property on the `AppError` object. If `result.error.retriable` is `true`, the operation can safely be retried after a delay or upon user request. Network timeouts and permission prompts typically set this flag to `true`, while validation errors and tool crashes set it to `false`.

### Where are PI Desktop error codes defined?

All error codes are defined in the `ErrorCodes` enum located in [`packages/shared/src/errors.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/errors.ts). This central registry includes codes for network failures (`NETWORK_ERROR`), tool denials (`TOOL_DENIED`), permission requirements (`PERMISSION_REQUIRED`), and host-core issues (`HOST_UNAVAILABLE`).

### How does PI Desktop handle errors from remote agents?

PI Desktop uses the RACP (Remote Agent Control Protocol) mapping layer in [`packages/shared/src/racp.ts`](https://github.com/vastsa/PI-Desktop/blob/main/packages/shared/src/racp.ts). The `toRacpErrorCode()` function translates local codes to remote equivalents (e.g., mapping `PERMISSION_TIMEOUT` to `APPROVAL_EXPIRED`), while `racpErrorIsRegistered()` ensures received codes map to known error types before being processed by the UI.