Additional

Troubleshooting

Synced from github.com/CoWork-OS/CoWork-OS/docs

macOS app won't launch with "Apple could not verify"

CoWork OS macOS DMGs are currently unsigned. On first launch, macOS may show "Apple could not verify CoWork OS is free of malware" or "CoWork OS" was blocked to protect your Mac.

Use the macOS Gatekeeper override:

  1. Drag CoWork OS from the DMG into Applications.
  2. Open CoWork OS once. If macOS blocks it, click Done.
  3. Open System Settings > Privacy & Security.
  4. Scroll to Security.
  5. Next to "CoWork OS" was blocked to protect your Mac, click Open Anyway.
  6. In the confirmation dialog, click Open Anyway again.

Release maintainers can create unsigned macOS DMG/ZIP artifacts with:

npm run package:mac:unsigned

Terminal fallback:

xattr -dr com.apple.quarantine "/Applications/CoWork OS.app"

If the app closes immediately with a dyld signature error:

codesign --force --deep --sign - "/Applications/CoWork OS.app"

spctl --add / spctl --enable are deprecated on newer macOS and may show "This operation is no longer supported".

npm install fails with SIGKILL

If install fails with SIGKILL during node_modules/electron/install.js, use a two-step install:

npm install --ignore-scripts cowork-os@latest --no-audit --no-fund
npm run setup

For local package testing, use the same --ignore-scripts flow with the tarball:

npm init -y
npm install --ignore-scripts /path/to/cowork-os-<version>.tgz

macOS "Killed: 9" during setup

If you see Killed: 9 during npm run setup, macOS terminated a native build due to memory pressure.

npm run setup already retries native setup automatically with backoff. Let it continue until it exits. If it still exits non-zero, close heavy apps and run the same command again:

npm run setup

Computer use issues

If screenshots fail or time out on macOS, grant Screen Recording for the helper path shown in Settings → Tools → Computer use, then quit and restart the app. If clicks or typing do nothing, enable Accessibility for that helper path the same way.

On Windows, keep the target window visible and non-minimized. If the target app is running as administrator, run CoWork with comparable privileges; protected apps may block capture or input.

If the agent never uses the computer-use tools, confirm Settings → Tools → Built-in tools includes the computer use category, and phrase tasks as native app / window / dialog work (not pure browser or CLI tasks).

See the full guide: Computer use.

Inbox Agent issues

Inbox Agent uses a local cache plus provider-backed actions. When debugging mailbox behavior, first capture a current development log:

npm run dev:log

Then inspect:

logs/dev-latest.log

For tooling or repeated-failure analysis, inspect logs/dev-latest.jsonl. It contains the same captured run as structured, redacted events with process, stream, level, component, and message fields.

New mail does not appear immediately

Inbox Agent autosyncs in the background, but it is not a push-only mail client yet. It loads cached mail immediately, then periodically refreshes a bounded recent batch. If a new message is missing:

  1. Wait for the next autosync interval.
  2. Use the refresh button in Inbox Agent to force a sync.
  3. Check logs/dev-latest.log for Mailbox autosync starting and Mailbox autosync complete.
  4. Confirm the account still shows connected sync health.

Unread count or unread styling looks wrong

Unread is provider-backed. Opening a thread may mark it read when provider permissions allow it. For Gmail, read/unread mutation requires the Gmail modify scope. If the app cannot mutate provider state, reconnect Google Workspace with the requested Gmail scopes or use the provider mailbox directly.

Mark read / unread / archive / trash says "Not connected"

The visible action is enabled only when the app has enough local context, but the provider mutation can still fail if the account token or channel connection expired. Reconnect the mailbox integration, then retry. Gmail server actions require Google Workspace to be enabled; IMAP/SMTP accounts have more limited server action support.

Ask Inbox does not find an email I can see

Ask Inbox searches local synced evidence first, then adds semantic mailbox matches, provider-native search where available, and attachment text when relevant. If a visible email is missing from Ask results:

  1. Confirm the thread exists in the Inbox Agent All view, not only in the external mail client.
  2. Use the Inbox Agent refresh button to sync the latest recent batch.
  3. If the answer is inside an attachment, open the thread and extract the attachment text, then retry the question.
  4. Check the Ask Inbox step feed to see which sources ran: local FTS, semantic index, provider search, attachment text, shortlist/read evidence, and answer generation.
  5. Inspect logs/dev-latest.log for mailbox ask/search errors if a step stops or reports an error.

Provider-native search is additive. If Gmail or Outlook/Microsoft Graph search fails, Ask Inbox should still fall back to local mailbox evidence and report related results when it has them.

See Ask Inbox Architecture.

@Gmail or @Inbox says Google Workspace authorization failed

The composer @ menu uses local configured state, so a stale Google token can still appear until the next provider call proves it is invalid. If a Gmail or Inbox request reports a Google Workspace token refresh bad request, CoWork clears the stale access/refresh tokens and requires a reconnect.

Fix:

  1. Open Settings > Integrations > Google Workspace.
  2. Confirm the client id, client secret, and scopes match the OAuth client you want to use.
  3. Click Connect again and finish the Google OAuth flow.
  4. Retry the @Gmail or @inbox prompt.

If you recently changed the Google OAuth client id, client secret, or scopes, reconnect even if the integration previously worked. Changed OAuth configuration invalidates the old token set.

The @ menu does not show an integration

The composer only shows configured integrations that are locally usable. It does not run live health checks while typing.

Check that the integration is enabled and has local credentials. For Google Workspace, the menu should show Gmail, Google Drive, and Google Calendar instead of a single Google Workspace item. For gateway channels such as Slack, the channel must be connected and enabled. For MCP connectors, the connector must be connected/configured.

See Composer Mentions.

Microphone next to Search threads fails after permission is allowed

The desktop app does not rely on Chromium's Web Speech service because it can request microphone permission but still fail when the speech-recognition backend is unavailable. Configure OpenAI or Azure speech-to-text in Settings > Voice. After that, Inbox Agent voice search and Speak reply use provider transcription.

AI draft does not disappear after send

Generated drafts are removed after a successful provider send. If the draft remains, check the visible error banner and the log for the provider send failure. The edited draft subject/body are saved before send, so a failed send should preserve your edits for retry.

Startup fails with a missing mailbox column

Mailbox schema migrations should add classification, Today/domain, attachment, and replacement-client columns automatically. If startup reports a missing column such as today_bucket, do not delete the app database. Capture logs/dev-latest.log and verify the schema migration path before trying destructive recovery.

PPTX previews only show text or speaker notes

CoWork can always extract slide text and presenter notes from .pptx files. The presentation viewer loads that fast text preview first, then renders slide images in the background. Rendered slide thumbnails are best-effort and use this order:

  1. Codex bundled @oai/artifact-tool presentation renderer.
  2. soffice from LibreOffice to convert the deck to PDF.
  3. pdftoppm to render PDF pages to PNG thumbnails.
  4. Text/notes preview if image rendering fails.

If artifact-tool is unavailable and either local binary is missing or fails on a deck, the presentation viewer stays in text/notes mode. Install LibreOffice and Poppler, restart CoWork, then reopen the artifact to regenerate the cached preview. The .pptx file itself is still available through Open file or Show in Finder.

Everything Workbench artifacts do not appear as cards

Generated documents, spreadsheets, presentations, web pages, PDFs, and previews should appear as first-class artifact cards when CoWork recognizes the output type. The shared flow is: output card, main Open action, sidebar workbench, fullscreen artifact workspace, follow-up composer, and refresh after completed edits.

If an output only appears as a plain file link:

  1. Confirm the file extension is one of the recognized artifact formats documented in Everything Workbench.
  2. Confirm the task emitted the file through file_created, file_modified, artifact_created, or primary completion output metadata.
  3. Reopen the task and use the artifact card's main Open action rather than an external-app dropdown action.
  4. Capture a fresh dev log if the card still does not appear.

Spreadsheet artifacts do not open in the sidebar

Local spreadsheet outputs should render as spreadsheet artifact cards. The main Open action opens .xlsx, .xls, .xlsm, .csv, and .tsv files in the in-app sidebar viewer. Native/app-owned spreadsheet formats such as .numbers, .gsheet, .ods, and .xlsb are recognized as spreadsheet artifacts, but open externally or through the folder action.

If a generated spreadsheet only appears as a plain file link or opens in the generic viewer:

  1. Confirm the output file extension is a recognized spreadsheet format such as .xlsx, .xls, .xlsm, .csv, .tsv, .numbers, .gsheet, .ods, or .xlsb.
  2. Confirm the file was emitted through file_created, artifact_created, or as the primary completion output.
  3. Reopen the task and click the main Open button, not an external-app dropdown item.
  4. If the viewer loads but grid data is missing, capture a dev log and check for spreadsheet parsing errors from readFileForViewer.

For a fresh repro log:

npm run dev:log

Then inspect:

logs/dev-latest.log

See Spreadsheet Artifacts for the expected sidebar/fullscreen behavior and the focused tests for this surface.

Document artifacts do not open or refresh correctly

Local Word-style outputs should render as document artifact cards. The main Open action opens .docx files in the in-app sidebar editor. .doc, .rtf, .odt, .ott, .pages, and related formats are recognized as document artifacts, but may use best-effort preview or external app actions depending on parser support.

If a generated document only appears as a plain file link, stays collapsed behind Output ready, or opens in the generic viewer:

  1. Confirm the output file extension is a recognized document format such as .docx, .docm, .dotx, .dotm, .doc, .rtf, .odt, .ott, or .pages.
  2. Confirm the file was emitted through file_created, file_modified, artifact_created, or as the primary completion output.
  3. Reopen the task and click the main Open button, not an external-app dropdown item.
  4. For DOCX editing, make sure the file is a real .docx document and not a renamed plain-text file.
  5. If a fullscreen follow-up completes but the document content does not update, capture a dev log and check for document preview or FILE_UPDATE_DOCUMENT errors.

For a fresh repro log:

npm run dev:log

Then inspect:

logs/dev-latest.log

See Document Artifacts for the expected sidebar/fullscreen behavior and the focused tests for this surface.

Web page artifacts do not open in the sidebar

Local web outputs should render as web page artifact cards. The main Open action opens generated .html and .htm files in the in-app sidebar viewer. Built React/Vite/Next output entrypoints such as dist/index.html, build/index.html, and out/index.html use the same sandboxed iframe preview.

If a generated web page only appears as a plain file link or opens in the generic viewer:

  1. Confirm the output file extension is .html or .htm, or that the output path points to a built index.html under dist, build, or out.
  2. Confirm the file was emitted through file_created, file_modified, artifact_created, or as the primary completion output.
  3. Reopen the task and click the main Open button, not an external-app dropdown item.
  4. If the project is React/Vite/Next source only, build it first so one of dist/index.html, build/index.html, or out/index.html exists. The artifact viewer intentionally does not auto-start dev servers.
  5. If the iframe opens but local assets are missing, capture a dev log and check for HTML asset inlining errors from readFileForViewer.

For a fresh repro log:

npm run dev:log

Then inspect:

logs/dev-latest.log

See Web Page Artifacts for the expected sidebar/fullscreen behavior and the focused tests for this surface.

Browser workbench does not open for website testing

Interactive browser-use prompts should open a visible browser workbench in the right sidebar. This is different from web page artifacts: generated .html files use the artifact iframe viewer, while live URLs use the Browser V2 workbench. See Browser Workbench for the expected controls, cursor overlay, screenshots, diagnostics, snapshot refs, and annotation behavior.

If a task like "go to example.com and test the application as a normal user" does not open the sidebar browser:

  1. Confirm the task used a browser_* tool such as browser_navigate, not only web_fetch. web_fetch is still correct for static page reading.
  2. Confirm the task is selected in the main task view. The visible workbench is tied to the selected task and opens on demand through the renderer.
  3. If the task explicitly requested force_headless, profile, browser_channel, or debugger_url, the tool will use the Playwright/external-CDP fallback path instead of the embedded workbench. The legacy headless flag alone should not bypass the visible workbench for normal site testing.
  4. If the site requires an existing signed-in Chrome or Edge session, use browser_attach explicitly and confirm real-browser control. The embedded browser uses a persistent workspace profile and does not silently reuse system Chrome cookies.
  5. Capture a fresh dev log and check for browserWorkbench:openRequest, browserWorkbench:register, BrowserSessionManager, or browser tool errors if the sidebar never appears.

If the sidebar opens but browser actions are hard to follow:

  1. Confirm the task is using visible browser_* tools rather than external Chrome attach or forced headless mode. Cursor movement is only rendered for the visible in-app webview.
  2. Confirm the Browser Workbench is still open for the selected task. Cursor events are scoped to { taskId, sessionId }.
  3. If snapshot refs fail as stale or unknown, call browser_snapshot again and retry with the new ref. Refs are valid only for the latest snapshot after page updates and navigation.
  4. If diagnostics look empty, confirm the task is using the visible Browser V2 workbench rather than forced Playwright or external CDP. Console/network/download/storage buffers are session-scoped.
  5. If screenshots or annotation fail, check that the task has an active workspace folder; captures are saved into the workspace before they can be attached back to the agent.

For a fresh repro log:

npm run dev:log

Then inspect:

logs/dev-latest.log

Task automation creation issues

If ... > Add automation... is missing from task view:

  1. Confirm you are viewing a local task, not a remote-session shadow task.
  2. Confirm the task belongs to a workspace. The save path requires a workspaceId.
  3. Reopen the task; the task title and three-dot menu are part of the selected task header.

If the modal opens but Save is disabled:

  1. Confirm the automation name is not empty.
  2. Confirm the prompt is not empty.
  3. Confirm the schedule is valid. Custom requires a non-empty cron expression.
  4. Use Chat or Local; Worktree is currently disabled until scheduled tasks can preserve task worktree context.

If Save returns an inline error, the modal is showing the addCronJob failure from the scheduler API. Check Settings > Automations > Scheduled Tasks after a successful save; task-sourced automations are stored there like any other cron job.

Chronicle desktop screen context issues

If Chronicle never seems to help with prompts like what is this on the right side or why is this failing, check these in order:

  1. Enable Chronicle in Settings > Memory Hub > Chronicle and accept the consent prompt.
  2. Confirm Settings > Tools > Built-in tools still has the Chronicle category enabled.
  3. Make sure the per-task Chronicle ON toggle was not turned off in the task composer or Devices panel.
  4. Confirm Screen Recording is granted for CoWork OS.
  5. If Chronicle is enabled but paused, resume it from the Chronicle settings card or the tray menu.
  6. Restart the app if Screen Recording was just changed.
  7. Leave the target window visible for 15-30 seconds so Chronicle has recent frames.
  8. Start a fresh task after enabling Chronicle.

For the first smoke test, use a deterministic prompt instead of a vague one:

Use screen_context_resolve now. Tell me what app and window are on screen and what text is visible on the right side.

What to look for:

  • the task trace should show a screen_context_resolve tool call
  • Mission Control task detail should later show screen_context evidence or recall hits
  • the Chronicle settings card should show a non-zero recent-screen frame count
  • the Chronicle settings card should show whether OCR is available and whether Screen Recording is actually granted
  • Settings > Memory Hub > Memory should show promoted entries under Chronicle observations

If the agent still asks you for a screenshot:

  • the task may have re-planned before invoking screen_context_resolve
  • the visible UI may not have had enough distinctive app/title/OCR text
  • the current run may not have had fresh passive frames yet
  • OCR-backed matches may be weaker if local tesseract is not installed

If you need a fresh repro log, run:

npm run dev:log

Then inspect:

logs/dev-latest.log

Use logs/dev-latest.jsonl when you need structured fields such as process, level, or component.

Look for lines such as:

  • Chronicle initialized (enabled=true, mode=hybrid)
  • screen_context_resolve

If those never appear, see Chronicle and Computer use.

Windows native setup fails (better-sqlite3)

If first launch exits after:

[cowork] $ npm.cmd rebuild --ignore-scripts=false better-sqlite3
[cowork] Native setup failed.

install native build prerequisites, then retry:

  1. Install Visual Studio Build Tools 2022 with:
    • Desktop development with C++
    • MSVC v143 build tools
    • Windows 10/11 SDK
  2. Install Python 3 and verify:
py -3 --version
  1. Set node-gyp MSVC env vars, then retry from a new terminal:
setx GYP_MSVS_VERSION 2022
setx npm_config_msvs_version 2022
cowork-os

Windows ARM64 note:

  • Setup now auto-tries x64 Electron emulation if ARM64 native rebuild fails.
  • To disable that fallback and force native ARM64 only, set COWORK_SETUP_SKIP_X64_FALLBACK=1.

App shows "vUnknown" or remote method error

If the app opens but shows vUnknown or Error invoking remote method 'app:getVersion', you likely connected to an older already-running instance.

pkill -f '/cowork-os' || true
cowork-os

Windows opens to a black screen (ERR_FILE_NOT_FOUND dist/renderer/index.html)

If terminal logs include:

Failed to load URL .../dist/renderer/index.html with error: ERR_FILE_NOT_FOUND

the published package is missing renderer build assets.

For users:

npm uninstall -g cowork-os
npm cache clean --force
npm install -g cowork-os@latest --no-audit --no-fund

For maintainers (before publish), verify tarball contains renderer assets:

npm run build
npm pack --json --dry-run | jq -r '.[0].files[].path' | grep '^dist/renderer/index.html
#x27;

VPS: "tsc: not found"

If you see sh: 1: tsc: not found right after npx coworkd-node, you are on an older broken npm publish. Upgrade and retry:

npm install cowork-os@latest --no-audit --no-fund

For production VPS installs, prefer the packaged Linux server release from GitHub Releases instead of the npm quick-start path. The package is named cowork-os-server-linux-x64-v<version>.tar.gz, includes built daemon assets, resources, connectors, and runtime dependencies, and runs with:

node bin/coworkd-node.js --print-control-plane-token

See Linux VPS for the full tarball + checksum + systemd flow.

"Tool-call budget exhausted: 42/42"

If you see:

Tool-call budget exhausted: 42/42

that means hard executor budget contracts are enabled.

Current default behavior:

  • COWORK_AGENT_BUDGET_CONTRACTS=false (opt-in only)

If your environment still enforces this cap, check for an explicit override and unset it:

unset COWORK_AGENT_BUDGET_CONTRACTS

Or explicitly disable it:

export COWORK_AGENT_BUDGET_CONTRACTS=false

To restore legacy strict budget-contract behavior, set:

export COWORK_AGENT_BUDGET_CONTRACTS=true

"web_search budget exhausted: X/Y"

If a research step logs:

web_search budget exhausted: 12/12

the task now uses a soft landing path for web-search-specific budget limits:

  • The web_search tool call returns a structured error (failureClass=budget_exhausted) instead of throwing a hard executor exception.
  • Execution can continue using already-collected evidence.
  • Terminal completion can resolve as partial_success (instead of being hard blocked), and budget-constrained failed steps are auto-waived in the completion gate when appropriate.

To tune behavior, use Guardrails > Web Search Policy:

  • Mode: disabled | cached | live
  • Max uses per task
  • Max uses per step
  • Allowed domains / Blocked domains

Notes:

  • cached is the default mode.
  • If strict cached provider behavior is unavailable, runtime falls back to live and emits web_search_mode_fallback_live.
  • Domain filtering emits web_search_domain_filtered_result_count. If all results are filtered, web_search returns a structured policy error.

LaTeX PDF compile fails or only creates .tex

The compile_latex tool uses a system TeX engine. CoWork OS does not bundle TeX Live, MacTeX, MikTeX, or Tectonic.

If a LaTeX/TikZ paper task leaves the .tex source but does not produce a PDF, check the task timeline for a compile_latex diagnostic. The most common message is:

No LaTeX engine found. Install tectonic, latexmk, xelatex, lualatex, or pdflatex and retry.

Fix:

  1. Install one supported engine on the machine running CoWork OS.
  2. Confirm the binary is on PATH with one of:
which tectonic
which latexmk
which xelatex
which lualatex
which pdflatex
  1. Retry the task or ask CoWork to compile the existing .tex file.

Notes:

  • Engine priority is tectonic, then latexmk, xelatex, lualatex, and pdflatex.
  • Paths are restricted to the active workspace.
  • A failed compile should still keep the editable .tex source as the durable artifact.
  • Successful compiles show a paired artifact workbench with Summary, .tex source, and PDF tabs.

Workflow Intelligence startup warnings in development

If npm run dev or npm run dev:log shows warnings like:

[AgentDaemon] Task requires git worktree isolation, but worktrees are unavailable for this workspace.
[Main] Failed to initialize SubconsciousLoopService: SqliteError: no such column: workspace_id
[Main] Failed to initialize SubconsciousLoopService: SqliteError: FOREIGN KEY constraint failed

those messages come from the Workflow Intelligence reflection service, not from the main Electron boot path itself. The log may still mention SubconsciousLoopService because that is the legacy internal service name.

What the warnings mean

Task requires git worktree isolation, but worktrees are unavailable for this workspace.

  • A code_change_task dispatch was considered for a target that requires isolated git execution.
  • The target workspace was not eligible for worktree use.
  • Common reasons: the workspace is not a real git repo, it is temporary, or worktree support is disabled/unavailable.

SqliteError: no such column: workspace_id

  • An earlier build queried legacy rows with an outdated column assumption during workflow-intelligence target collection.
  • Startup could continue, but SubconsciousLoopService would fail to initialize.

SqliteError: FOREIGN KEY constraint failed

  • An earlier migration path could fail while rekeying legacy improvement records into workflow-intelligence target history.
  • This was a migration bug, not a sign that the feature requires manual owner enrollment or a separate approval step.

Current fix

Current builds harden the startup path in several places:

  1. SubconsciousLoopService starts after memory services are initialized. This is the internal service behind Workflow Intelligence.
  2. Code dispatch only targets real git-backed repositories, and canonical code targets resolve from the repository remote instead of from transient workspace noise.
  3. Legacy improvement rows are migrated into workflow-intelligence target state without breaking foreign keys.
  4. Worktree settings persist in secure settings so code dispatch can still require isolation after restart.
  5. Recommendation-only runs still complete successfully when a target has no valid executor mapping.

How to verify

Use the timestamped dev logger:

npm run dev:log

Then inspect:

logs/dev-latest.log

If the readable log is noisy, use logs/dev-latest.jsonl to filter by structured level and component.

Healthy startup should include:

  • SubconsciousLoopService initialized
  • no Failed to initialize SubconsciousLoopService line
  • no early worktree failure for a non-git temporary workspace unless a real code target was incorrectly selected

If you still see the worktree warning

Check:

  1. the workspace path is inside a real git repository
  2. the repo remote resolves to the intended repository
  3. git worktree support is enabled
  4. the repository is usable from the app runtime environment

If you use non-git workspaces, Workflow Intelligence can still run on task, mailbox, schedule, trigger, and briefing targets. Only code-change auto-create requires the git/worktree path.

If you still see SQLite initialization errors

Capture a fresh log and compare the relative timestamps for:

  • MemoryService initialization
  • SubconsciousLoopService initialized
  • the first workflow-intelligence target refresh or run line

If initialization still fails on a current build, inspect the local database migration path before looking at renderer or approval code.

See also: