codex - 💡(How to fix) Fix danger-full-access sandbox blocks Metal/GPU IOKit access, crashing MLX on macOS [4 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openai/codex#17644Fetched 2026-04-14 05:41:52
View on GitHub
Comments
4
Participants
3
Timeline
7
Reactions
0
Author
Timeline (top)
commented ×4labeled ×3

When Codex spawns a Python subprocess that imports mlx.core (e.g., for local voice transcription via mlx-whisper), the process crashes with SIGABRT due to an uncaught NSRangeException:

*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

The crash occurs in mlx::core::metal::Device::Device() during Metal GPU device enumeration. Metal's MTLCopyAllDevices() returns an empty array because the Seatbelt sandbox profile restricts IOKit access.

Error Message

This crashes with the identical NSRangeException:

sandbox-exec -p '(version 1)(allow default)(deny iokit-open)'
python3 -c "import mlx.core"

This works fine (full IOKit access):

sandbox-exec -p '(version 1)(allow default)'
python3 -c "import mlx.core; print(mlx.core.default_device())"

Root Cause

The Seatbelt profile compiled into the Codex binary only allows:

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient"))

This applies even in danger-full-access mode. Metal GPU enumeration requires IOKit access to GPU driver classes (e.g., AGXMetalG16X on Apple Silicon), which is not permitted.

Code Example

*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

---

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient"))

---

# This crashes with the identical NSRangeException:
sandbox-exec -p '(version 1)(allow default)(deny iokit-open)' \
  python3 -c "import mlx.core"

# This works fine (full IOKit access):
sandbox-exec -p '(version 1)(allow default)' \
  python3 -c "import mlx.core; print(mlx.core.default_device())"

---

(allow iokit-open)

---

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient")
  (iokit-registry-entry-class "AGXDeviceUserClient")
  (iokit-registry-entry-class "IOGPUDeviceUserClient"))

---

Process:     Python
Parent:      codex
Exception:   EXC_CRASH (SIGABRT)
Reason:      *** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

Crash thread backtrace:
  CoreFoundation  -[__NSArray0 objectAtIndex:]
  libmlx.dylib    mlx::core::metal::Device::Device()
  libmlx.dylib    mlx::core::metal::device(mlx::core::Device)
  libmlx.dylib    mlx::core::metal::MetalAllocator::MetalAllocator()
  libmlx.dylib    mlx::core::allocator::allocator()
  libmlx.dylib    mlx::core::random::key(unsigned long long)
  core.cpython-314-darwin.so  [module init]
RAW_BUFFERClick to expand / collapse

Environment

  • codex-cli 0.118.0
  • macOS 26.4 (25E246), Apple M4 Pro
  • Python 3.14.2, MLX 0.31.0
  • Config: sandbox = "danger-full-access", bypass-sandbox = true, CLI alias with --dangerously-bypass-approvals-and-sandbox

Description

When Codex spawns a Python subprocess that imports mlx.core (e.g., for local voice transcription via mlx-whisper), the process crashes with SIGABRT due to an uncaught NSRangeException:

*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

The crash occurs in mlx::core::metal::Device::Device() during Metal GPU device enumeration. Metal's MTLCopyAllDevices() returns an empty array because the Seatbelt sandbox profile restricts IOKit access.

Root Cause

The Seatbelt profile compiled into the Codex binary only allows:

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient"))

This applies even in danger-full-access mode. Metal GPU enumeration requires IOKit access to GPU driver classes (e.g., AGXMetalG16X on Apple Silicon), which is not permitted.

Reproduction

Minimal reproduction without Codex, confirming the Seatbelt IOKit restriction is the root cause:

# This crashes with the identical NSRangeException:
sandbox-exec -p '(version 1)(allow default)(deny iokit-open)' \
  python3 -c "import mlx.core"

# This works fine (full IOKit access):
sandbox-exec -p '(version 1)(allow default)' \
  python3 -c "import mlx.core; print(mlx.core.default_device())"

Expected Behavior

danger-full-access mode (and --dangerously-bypass-approvals-and-sandbox) should grant unrestricted IOKit access, allowing Metal/GPU operations in child processes.

Suggested Fix

Add an unrestricted IOKit rule to the danger-full-access sandbox template:

(allow iokit-open)

Or, if a scoped approach is preferred:

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient")
  (iokit-registry-entry-class "AGXDeviceUserClient")
  (iokit-registry-entry-class "IOGPUDeviceUserClient"))

Crash Report (abbreviated)

Process:     Python
Parent:      codex
Exception:   EXC_CRASH (SIGABRT)
Reason:      *** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

Crash thread backtrace:
  CoreFoundation  -[__NSArray0 objectAtIndex:]
  libmlx.dylib    mlx::core::metal::Device::Device()
  libmlx.dylib    mlx::core::metal::device(mlx::core::Device)
  libmlx.dylib    mlx::core::metal::MetalAllocator::MetalAllocator()
  libmlx.dylib    mlx::core::allocator::allocator()
  libmlx.dylib    mlx::core::random::key(unsigned long long)
  core.cpython-314-darwin.so  [module init]

extent analysis

TL;DR

Add an unrestricted IOKit rule to the danger-full-access sandbox template to allow Metal/GPU operations in child processes.

Guidance

  • Verify that the crash occurs due to the Seatbelt sandbox profile restricting IOKit access by running the minimal reproduction command.
  • Consider adding an unrestricted IOKit rule to the danger-full-access sandbox template: (allow iokit-open).
  • Alternatively, use a scoped approach by adding specific IOKit registry entry classes: (allow iokit-open (iokit-registry-entry-class "AGXDeviceUserClient") (iokit-registry-entry-class "IOGPUDeviceUserClient")).
  • Test the fix by running the reproduction command with the updated sandbox template.

Example

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient")
  (iokit-registry-entry-class "AGXDeviceUserClient")
  (iokit-registry-entry-class "IOGPUDeviceUserClient"))

Notes

The suggested fix assumes that granting unrestricted IOKit access is acceptable in danger-full-access mode. However, this may introduce security risks, and a more scoped approach may be preferred.

Recommendation

Apply the workaround by adding an unrestricted IOKit rule to the danger-full-access sandbox template, as it is the most straightforward solution to allow Metal/GPU operations in child processes.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING