[BUG] Claude Desktop linux-arm64: no local Claude Code session is ever persisted — bundled Electron 42.10.0 has wrong fcntl constants, every private-dir write fails with EINVAL

Status Open
Reported on v2.1.246
Maintainer reply None cached
Activity 1 comment · opened Aug 30, 2026

Preflight Checklist

  • [X] I have searched existing issues and this hasn't been reported yet
  • [X] This is a single bug report (please file separate reports for different bugs)
  • [X] I am using the latest version of Claude Code

What's Wrong?

On Claude Desktop for Linux arm64, no local Claude Code session is ever persisted. Start a session, close the app, reopen it: the session is gone from the sidebar and its project group has disappeared.

The Claude Code transcripts themselves are fine — they are all in ~/.claude/projects/<slug>/*.jsonl. It is Claude Desktop's own session index that never gets written. ~/.config/Claude/claude-code-sessions/<account>/<org>/ stays empty forever.

It is not only sessions. Every private-directory write in the app fails the same way:

claude-code-sessions/<account>/<org>/                          local Claude Code sessions
local-agent-mode-sessions/<account>/<org>/                     agent-mode sessions
local-agent-mode-sessions/<account>/<org>/rpm
local-agent-mode-sessions/skills-plugin/<org>/<account>/skills
claude-code/2.1.246, claude-code/2.1.247                       bundled CLI updater

claude-code/2.1.247/ was created but left empty, so the bundled CLI cannot self-update either. [CCDScheduledTasks] Failed to save scheduled tasks fails for the same reason.

The cause is the bundled Electron 42.10.0, whose linux-arm64 build reports the x86-64 fcntl constants. Filed upstream as electron/electron#53315. Reporting it here because it is this app that breaks for the user, and because there is a fix available to you immediately: Electron 43.4.1 is verified good on linux-arm64.

What Should Happen?

Local Claude Code sessions should be written to ~/.config/Claude/claude-code-sessions/<account>/<org>/ and restored on the next launch, in their project group.

Error Messages/Logs

# ~/.config/Claude/logs/main.log — 72 occurrences before patching
[error] Failed to save session local_<id>: EINVAL: invalid argument,
        open '~/.config/Claude/claude-code-sessions/<account>/<org>'
    at async open (node:internal/fs/promises)
    at async $r (index.chunk-Cv8AY_mc.js)
    at async ensureStorageDir (index.chunk-Cv8AY_mc.js)
    at async writeSnapshotToDisk

[info] Loaded 0 persisted sessions from ~/.config/Claude/claude-code-sessions/<account>/<org>

[error] [CCDScheduledTasks] Failed to save scheduled tasks: EINVAL: invalid argument,
        open '~/.config/Claude/claude-code-sessions/<account>/<org>'

Steps to Reproduce

  1. On Linux aarch64, install claude-desktop 1.40609.0 (official arm64 .deb).
  2. Open Claude Desktop, switch to Code, pick any folder, start a local Claude Code session and send one message.
  3. Observe ~/.config/Claude/claude-code-sessions/<account>/<org>/ — it stays empty, and main.log logs the EINVAL above.
  4. Quit and reopen the app.

The session is gone from the sidebar; main.log shows Loaded 0 persisted sessions.

This reproduces on every launch. It is not intermittent and it is not state-dependent — the write has never once succeeded on this machine.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.246 (bundled in Claude Desktop 1.40609.0); standalone CLI 2.1.251, which is unaffected

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

Debian forky/sid, Linux 7.2.2 aarch64 (Snapdragon X1P42100), ext4. Claude Desktop 1.40609.0 arm64, Electron 42.10.0 / Node 24.18.1.

Root cause. The private-directory helper calls:

open(dir, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | (constants.O_NOFOLLOW ?? 0))

The bundled Electron reports the x86-64 values rather than the aarch64 ones:

| constant | reported | correct on aarch64 |
| --- | --- | --- |
| O_DIRECTORY | 65536 | 16384 |
| O_NOFOLLOW | 131072 | 32768 |
| O_DIRECT | 16384 | 65536 |

On aarch64 those bits mean O_DIRECT | O_LARGEFILE, and O_DIRECT on a directory returns EINVAL. Confirmed by flipping the runAsNode fuse on a copy of the shipped binary:

$ ELECTRON_RUN_AS_NODE=1 ./claude-desktop-copy probe.js
{"node":"24.18.1","electron":"42.10.0","arch":"arm64",
 "O_DIRECTORY":65536,"O_NOFOLLOW":131072,"O_DIRECT":16384}

This is upstream Electron's bug, not yours: the untouched official electron-v42.10.0-linux-arm64.zip behaves identically. It affects every Electron linux-arm64 release published from 2026-08-24 on (42.10.0, 42.10.1, 44.0.0) across three branches, while everything up to 43.4.1 (2026-08-19) is fine — same Node 24.18.1 on both sides, so it is the arm64 build environment. Details in electron/electron#53315.

Security note. Your helper passes O_NOFOLLOW to guard against a symlink being planted at the private-dir path (Refusing non-directory at private dir path (symlink/file plant)). Under the wrong constants O_NOFOLLOW becomes O_LARGEFILE, a no-op on 64-bit — so on arm64 that defence is silently absent whenever the open() does succeed.

Confirmation. I patched app.asar locally, replacing every read of those three constants with the correct aarch64 literals (54 sites across 13 .js entries, same-length replacements so the asar header and offsets stay valid). After a restart:

EINVAL occurrences         : 0
claude-code-sessions/<account>/<org>/
  local_<id>.json          5910 bytes
  scheduled-tasks.json      125 bytes
[info] Loaded 1 persisted sessions from …/claude-code-sessions/…

Nothing else changed.

Suggested fix. Ship the arm64 build on an Electron release predating the upstream regression — 43.4.1 is verified good — until upstream is fixed. A defensive alternative that costs nothing: derive those three flags from process.arch instead of trusting fs.constants, or drop O_DIRECTORY/O_NOFOLLOW from the flags and rely on the fstat().isDirectory() check you already perform right after the open().

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗