[BUG] Claude in Chrome `file_upload` rejects all scheduled-task sessions with misleading error (real cause: INVALID_SESSION)
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?
mcp__Claude_in_Chrome__file_upload rejects every file path when called from a Claude Code Desktop scheduled task, with a misleading error message:
Cannot upload "/path/to/file": only files the user has shared with this session can be uploaded.
The real cause (from main.log) is INVALID_SESSION, not a permission/sharing issue. Claude Desktop has two parallel session managers — CCD (used by scheduled tasks) and cowork (used by interactive chat) — and the Chrome MCP file_upload validator (Gv in app.asar) only consults the cowork manager (Ci). For CCD session IDs, Ci.getSession() returns null, so the validator throws [INVALID_SESSION] Unknown session: ... before ever reading the allowlist. The catch wrapper (Bcr / chromeFileUpload) re-emits this as the generic "shared with this session" message the user sees.
This makes file_upload structurally unusable from any CCD scheduled task. No permission/folder/sharing config the user can set will fix it — the session is rejected before the allowlist is consulted.
What Should Happen?
Either:
(a) file_upload should succeed for CCD scheduled-task sessions the same way it does for interactive cowork sessions — by having Gv consult both session managers (ln and Ci), and sourcing the allowlist for CCD sessions from the scheduled-task record's userSelectedFolders field (which is already preserved by the JSON writer but never read);
OR at minimum
(b) the error should surface the real INVALID_SESSION reason instead of masking it as "only files the user has shared". The current message sent me down hours of dead-end debugging trying to "share" the file in every conceivable way (which is impossible for CCD sessions — the validator throws before the allowlist is even checked).
Error Messages/Logs
From ~/Library/Logs/Claude/main.log (test run 2026-05-28):
2026-05-28 11:31:32 [info] Starting local session local_2baaad08-b19c-4a36-8565-fbf84e649d70 in /Users/mmhw/Downloads/MO
2026-05-28 11:31:33 [info] Mapping internal session local_2baaad08-... to CLI session 24635ca6-7c44-4fcd-afe6-2dc61c073d1f
2026-05-28 11:31:36 [info] [CCD start-timing] local_2baaad08-... preflight=801ms ... total_to_assistant=4343ms
...
2026-05-28 11:33:20 [warn] uploadLocalFile: unknown local agent mode session local_2baaad08-b19c-4a36-8565-fbf84e649d70
2026-05-28 11:33:20 [warn] [chromeFileUpload] rejected path for session local_2baaad08-b19c-4a36-8565-fbf84e649d70: /Users/mmhw/Downloads/MO/Standard Audio - Heidi.m4a ([INVALID_SESSION] Unknown session: local_2baaad08-b19c-4a36-8565-fbf84e649d70)
The [CCD start-timing] line confirms the session was spawned via the CCD path. The [chromeFileUpload] line shows the real INVALID_SESSION error that's then re-wrapped as the misleading user-facing message.
User-facing error returned to the SKILL:
> Cannot upload "/Users/mmhw/Downloads/MO/Standard Audio - Heidi.m4a": only files the user has shared with this session can be uploaded.
Steps to Reproduce
- Have Claude Desktop running on macOS with the Claude in Chrome extension installed + connected + authenticated.
- Create a CCD scheduled task — either via the /schedule skill, or by adding an entry to ~/Library/Application Support/Claude/claude-code-sessions/<workspace>/scheduled-tasks.json with cwd, cronExpression, and filePath pointing to a SKILL.md.
- The SKILL.md should: open any web page containing an <input type="file"> element via mcp__Claude_in_Chrome__navigate, find the input via mcp__Claude_in_Chrome__find, then call:
mcp__Claude_in_Chrome__file_upload({
paths: ["/Users/<you>/Downloads/anyfile.m4a"],
ref: "<ref from find>",
tabId: <tabId>
})
- Wait for the cron to fire. file_upload returns the rejection error 100% of the time, regardless of file location.
Things I tried that did NOT fix it (all empirically verified):
- Adding userSelectedFolders: ["/Users/.../Downloads/MO"] to the task record in scheduled-tasks.json (preserved on disk; never propagated to the spawned CCD session JSON; validator throws INVALID_SESSION before reading allowlist anyway)
- Moving the file to /tmp, ~/.claude/, or the task's cwd
- @/folder mention in chat
- Restarting Claude Desktop
I traced the root cause in /Applications/Claude.app/Contents/Resources/app.asar → .vite/build/index.js: Gv only calls Ci.getSession() (cowork manager); CCD session IDs return null; Bcr wraps the thrown error as the generic catch-all message. The CCD buildSessionStartEvent schema (OXt) also explicitly drops userSelectedFolders / userSelectedFiles even when set on the scheduled-task record.
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
2.1.149
Claude Code Version
Claude Code running inside Claude Desktop 1.9255.2
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Workaround in use: the affected task (tb-prep---heidi, daily 5 AM Heidi audio prep) now creates per-patient Heidi session shells with names pre-filled, then sends a desktop notification telling the user how many shells need manual audio upload + template application. The user opens each in their browser and does the file pick + template by hand.
Three suggested fixes ranked smallest → largest scope:
- Surface the real INVALID_SESSION error to the user instead of masking it as "only files the user has shared". Even a one-line addition like "(INVALID_SESSION: this session manager isn't recognized by file_upload; this may be a CCD scheduled task)" would have saved hours of dead-end debugging.
- Have Gv consult both session managers (ln and Ci). For CCD sessions, source the allowlist from the scheduled-task record's userSelectedFolders field (already preserved by the JSON writer; just never read on the spawn path).
- Unify the spawn paths so CCD buildSessionStartEvent carries userSelectedFolders / userSelectedFiles through the same as cowork's, registers CCD sessions in a unified registry, and lets Gv work uniformly.
Relevant files for engineering:
- /Applications/Claude.app/Contents/Resources/app.asar → .vite/build/index.js (functions Gv, Bcr, OXt, Ci, ln, CCD vs cowork buildSessionStartEvent)
- ~/Library/Logs/Claude/main.log (the [chromeFileUpload] rejected path warnings)
- ~/Library/Application Support/Claude/claude-code-sessions/<workspace>/scheduled-tasks.json (CCD task records)
- ~/Library/Application Support/Claude/claude-code-sessions/<workspace>/local_<id>.json (CCD session JSON — note userSelectedFolders key absent)
- ~/Library/Application Support/Claude/local-agent-mode-sessions/<workspace>/local_<id>.json (cowork session JSON — userSelectedFolders: [] present as explicit empty array)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗