Error in Obsidian+CLI+Claude Setup

Obsidian Crash — Root Cause Analysis

What happened

Obsidian quit unexpectedly mid-session. The Claude Code session that was running at the time also
crashed without executing its close protocol (agent-status was still “Session active” on next
startup, Kanban had partially-moved tasks).

Root cause: NSPersistentUI secure coding failure

The crash originated in macOS AppKit’s window state restoration system, not in Obsidian’s code or
any community plugin.

The chain:

  1. macOS persists window state (size, position, tab layout) for every app in ~/Library/Saved
    Application State/.savedState/
  2. For Obsidian, that’s ~/Library/Saved Application State/md.obsidian.savedState/
  3. On relaunch, AppKit deserializes these NSCoder archives using +[NSKeyedUnarchiver
    unarchivedObjectOfClass:fromData:error:] — which enforces secure coding (the object’s class must be
    explicitly allowlisted during decoding)
  4. Electron (Obsidian’s runtime) wraps Chromium’s BrowserWindow inside a native NSWindow. The state
    restoration archive can contain Electron/Chromium internal classes that macOS doesn’t recognize as
    allowlisted for secure decoding
  5. When this mismatch happens, NSCoderReadCorruptError fires, and AppKit terminates the app before
    it finishes launching

Why it hit this machine specifically:

  • macOS Monterey 12.7.6 — Apple tightened NSSecureCoding enforcement across several Monterey point
    releases. Newer macOS versions have had more time to stabilize the Electron ↔ AppKit interface
  • Obsidian 1.12.7 on Electron — the specific Electron version may serialize window state objects
    that Monterey’s stricter decoder rejects on restore
  • This is a known class of Electron-on-macOS bugs. It’s a timing/compatibility issue between the
    Electron shell and macOS’s native state restoration, not a logic error in Obsidian or its plugins

Why it’s NOT plugin-related

  • The crash happens before Obsidian’s JS runtime initializes — it’s in the native Cocoa layer
    during applicationDidFinishLaunching:
  • No community plugin code runs at that point
  • Disabling plugins wouldn’t help because the failure is in deserialization of the NSWindow state
    archive, which is managed by macOS, not Obsidian

The fix

rm -rf ~/Library/Saved\ Application\ State/md.obsidian.savedState/

This deletes the corrupted window state archive. On next launch, macOS has nothing to restore, so
it skips the NSSecureCoding deserialization entirely. Obsidian opens fresh with default window
geometry.

This is non-destructive — it only removes macOS’s cached window positions/sizes. No vault data,
plugin config, or Obsidian settings are affected. Those live in .obsidian/ inside the vault
directory.

Longer-term mitigation

  • Update Obsidian — newer versions ship newer Electron, which is more likely to serialize state
    objects that Monterey’s decoder accepts
  • Update macOS — if feasible, moving past Monterey removes the specific NSSecureCoding strictness
    that triggers this
  • Preventive: You could add a launch agent or alias that clears savedState before every Obsidian
    launch, but that’s heavy-handed — the crash is intermittent, not guaranteed on every launch

TL;DR for devs

▎ macOS Monterey’s NSPersistentUI tries to deserialize Electron’s NSWindow state on app launch. If
the serialized objects fail NSSecureCoding validation (class not in allowlist), AppKit kills the
process before the app even loads. Fix: nuke ~/Library/Saved Application
State/md.obsidian.savedState/. It’s a macOS ↔ Electron compatibility bug, not an Obsidian bug.