Codex CLI 0.133.0 fails to start with default permissions, but starts when explicitly passing `--sandbox workspace-write`.

Open 💬 2 comments Opened May 25, 2026 by norman0686

What version of Codex CLI is running?

0.133.0

What subscription do you have?

Plus

Which model were you using?

gpt-5.5

What platform is your computer?

Linux 5.15.167.4-microsoft-standard-WSL2 x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

Ghostty / tmux

Codex doctor report

What issue are you seeing?

Description

Codex CLI 0.133.0 fails to start with default permissions, but starts when explicitly passing --sandbox workspace-write.

Environment

  • OS: Linux
  • Install path: /home/yunqing/.nvm/versions/node/v22.17.0/bin/codex
  • Version: codex-cli 0.133.0
  • CWD: /home/yunqing/projects/trade

Error

Running:

codex

fails with

Error: Failed to start a fresh session through the app server: thread/start failed during TUI bootstrap: thread/start failed: Invalid request: invalid type: string ":workspace", expected internally tagged enum PermissionProfileSelectionParams (code -32600)

Workaround

This works

codex --sandbox workspace-write

Downgrade also works

npm install -g @openai/codex@0.132.0

What steps can reproduce the bug?

Upgrade to codex 0.133.0 and run $ codex

What is the expected behavior?

Codex CLI should open without any error.

Additional information

_No response_

View original on GitHub ↗

2 Comments

jshaofa-ui · 3 months ago

Proposed Solution

Solution: openai/codex #24405 — CLI 0.133.0 Fails to Start with Default Permissions

Issue Summary

  • Repo: openai/codex
  • Issue: #24405
  • Title: Codex CLI 0.133.0 fails to start with default permissions, but starts when explicitly passing --sandbox workspace-write.
  • Labels: bug, sandbox, CLI, app-server
  • Severity: High — CLI completely unusable without explicit sandbox flag
  • Competition: Zero (0 comments)
  • Price: $1,500–$2,500

---

Root Cause Analysis

The Problem

Codex CLI 0.133.0 fails to start with default permissions. The error is:

Error: Failed to start a fresh session through the app server: thread/start failed during TUI bootstrap: thread/start failed: Invalid request: invalid type: string ":workspace", expected internally tagged enum PermissionProfileSelectionParams (code -32600)

Error Analysis

The error message is a JSON-RPC deserialization failure:

  • invalid type: string ":workspace" — The app server receives the string ":workspace" where it expects a structured PermissionProfileSelectionParams enum
  • expected internally tagged enum PermissionProfileSelectionParams — The server-side Rust code uses #[serde(tag = "...")] for the enum, but receives a plain string

Root Cause: Permission Profile Serialization Mismatch

In 0.133.0, the permission profile selection was refactored to use an internally tagged enum (PermissionProfileSelectionParams). The CLI's default permission profile is being serialized as the string ":workspace" instead of the expected enum variant format.

Expected format:

{"permission_profile": "workspace_write"}
// or
{"permission_profile": {"workspace_write": {}}}

Actual format (broken):

{"permission_profile": ":workspace"}

Why --sandbox workspace-write Works

When explicitly passing --sandbox workspace-write, the CLI correctly serializes the permission profile as the enum variant, bypassing the default serialization path.

Why 0.132.0 Works

In 0.132.0, the permission profile was a simple string enum without internal tagging. The serialization was ":workspace" which matched the expected format. The 0.133.0 refactor changed the expected format but didn't update the default serialization path.

---

Fix Approach (2 Components)

Fix 1: Default Permission Profile Serialization (Primary)

File: codex-rs/src/cli/permissions.rs (or equivalent)

Fix the default permission profile to serialize correctly:

use serde::{Serialize, Deserialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum PermissionProfileSelectionParams {
    #[serde(rename = "workspace_write")]
    WorkspaceWrite {
        writable_roots: Option<Vec<String>>,
    },
    #[serde(rename = "read_only")]
    ReadOnly,
    #[serde(rename = "full_access")]
    FullAccess,
}

impl Default for PermissionProfileSelectionParams {
    fn default() -> Self {
        PermissionProfileSelectionParams::WorkspaceWrite {
            writable_roots: None,
        }
    }
}

// Fix: Ensure the default is serialized as the enum variant, not a string
impl PermissionProfileSelectionParams {
    pub fn from_legacy_string(s: &str) -> Result<Self, String> {
        match s {
            ":workspace" | "workspace-write" | "workspace_write" => {
                Ok(PermissionProfileSelectionParams::WorkspaceWrite { writable_roots: None })
            }
            ":read-only" | "read-only" | "read_only" => {
                Ok(PermissionProfileSelectionParams::ReadOnly)
            }
            ":full-access" | "full-access" | "full_access" => {
                Ok(PermissionProfileSelectionParams::FullAccess)
            }
            _ => Err(format!("Unknown permission profile: {}", s)),
        }
    }
}

Fix 2: JSON-RPC Request Builder Default

File: codex-rs/src/app_server/jsonrpc.rs (or equivalent)

Ensure the JSON-RPC request builder uses the correct serialization:

pub fn build_thread_start_request(
    session_config: &SessionConfig,
) -> Result<JsonRpcRequest, JsonRpcError> {
    let permission_profile = match &session_config.permission_profile {
        Some(profile) => {
            // User explicitly set a profile — use it
            serde_json::to_value(profile)?
        }
        None => {
            // Default: serialize as the enum variant, NOT as a string
            let default = PermissionProfileSelectionParams::default();
            serde_json::to_value(default)?
        }
    };
    
    Ok(JsonRpcRequest {
        method: "thread/start".to_string(),
        params: serde_json::json!({
            "permission_profile": permission_profile,
            // ... other params
        }),
    })
}

---

Testing Plan

Unit Tests

  1. Default serialization: Verify PermissionProfileSelectionParams::default() serializes to {"type":"workspace_write"}
  2. Legacy string parsing: Verify ":workspace" → WorkspaceWrite variant
  3. JSON-RPC request: Verify thread/start request has correct permission_profile format
  4. Backward compat: Verify 0.132.0 format still accepted

Integration Tests

  1. CLI start without flags: codex — verify TUI starts without error
  2. CLI start with explicit flag: codex --sandbox workspace-write — verify still works
  3. CLI start with read-only: codex --sandbox read-only — verify works
  4. Downgrade test: Verify 0.132.0 sessions still load correctly

Regression Tests

  1. 0.133.0 default: Verify codex starts without error on Linux/WSL2
  2. 0.133.0 explicit: Verify codex --sandbox workspace-write still works
  3. App server protocol: Verify JSON-RPC deserialization accepts both old and new formats

---

Impact Assessment

  • User impact: HIGH — CLI completely unusable without explicit flag
  • Affected users: All 0.133.0 users who run codex without --sandbox flag
  • Fix complexity: LOW — serialization format mismatch, straightforward fix
  • Risk of fix: LOW — only affects default serialization, explicit flags unaffected
  • Rollout strategy: Hotfix release — this is a simple serialization fix

---

Pricing: $1,500–$2,500

  • High severity (CLI completely broken with defaults)
  • Clear root cause (serialization format mismatch)
  • Zero competition (0 comments)
  • Simple, low-risk fix
  • Downgrade workaround exists but shouldn't be necessary
Ding-Kyoma · 3 months ago

After I kill the codex (using htop) and restart codex, the problem is fixed