Troubleshooting
The Editor or Database tab shows an error
Both spawn an external binary. code-server and dbgate-serve are separate installs (see installation); when one is missing, the tab reports it in the status line rather than hanging.
DbGate can also fail because it never began listening. Its port is discovered by reading its own startup line, so a version that changes that line fails loudly here rather than silently.
The Editor, Database or Cluster tab takes a long time to open
The wait is the binary's own start-up, not Jarvis's. Measured here: code-server about a second warm and nine cold, dbgate-serve about a second warm and twenty-two cold, headlamp-server about twelve seconds cold — "cold" meaning its files are not in the page cache, which is the first open after a reboot. The toolbar says which one it is waiting for and the button is disabled until it answers, so a slow start looks like a slow start rather than a frozen app.
Hover the button a moment before clicking it. That begins the spawn early and the click joins it; it turns a five-second wait into about a tenth of a second. Nothing is spawned twice — the manager shares one start per project.
An instance no open tab has needed for ten minutes is stopped, so a tab you come back to in the afternoon pays a start again — a warm one, since its files are still in the page cache. performance.stopSidecarsAfterMinutes is the number, and 0 keeps every instance until Jarvis quits. See configuration.
If DbGate genuinely never answers, its instance is killed after sixty seconds and the status line says so.
A hosted page does not fill its slot
A browser or editor page leaving a band of empty window down the right, or overlapping the bookmarks sidebar on the left, means the rectangle main was given is in different units from the ones it placed the view with. The renderer measures in CSS pixels; a view is placed in device-independent pixels, and those differ on a display running a scaled resolution.
Jarvis converts for this (devicePixelRatio / scaleFactor, per the display the window is actually on) so dragging the window between monitors of different scales is handled. If it recurs, it is a bug in that conversion — check view-bounds.ts, and compare the hosted view's width against the window in DIP, never against the slot in CSS pixels, which is the comparison that hides the fault.
A request says "fetch failed — connect ECONNREFUSED ::1:8088"
Nothing is listening. Note the ::1: localhost resolves to IPv6 first on macOS, so a server bound only to 127.0.0.1 is not reachable as localhost. Either bind it to both, or write 127.0.0.1 in the environment.
A request says "No value for: apiKey"
The selected environment has no such variable. The request was still sent, with left as written — see the API client for why that is deliberate.
The Database tab asks for a login every time
By design. DbGate has no way to bind to loopback, so each instance is guarded by a credential generated when it starts. It changes when Jarvis restarts.
The Cluster tab says it cannot open, and it worked yesterday
Jarvis does not manage cluster credentials. A kubeconfig context that authenticates through an exec plugin — gcloud, kubelogin — needs a session that is already valid, and a spawned server has no terminal to prompt in. Log in the way you normally would (aws sso login, and check with kubectl get ns), then press the button again. Lens behaves the same way for the same reason.
AWS is the exception. For a context whose plugin is aws eks get-token, the button logs you in itself: it opens a Terminal tab, runs saml2aws login && aws eks update-kubeconfig …, and carries on to the cluster once that succeeds. Approve the MFA push when it arrives. If it does not finish, see below.
If the tab opens but the page itself reports the cluster as unreachable, headlamp-server says why: its output is printed to the terminal Jarvis was launched from, prefixed [headlamp].
The Cluster tab shows clusters from another project
This should not happen; if it does, the context names in clusters: do not match the kubeconfig exactly. The filter Jarvis passes to headlamp-server matches on the exact context name, so a name that is close but not identical is treated as a different cluster and left visible rather than hidden.
The button says "Could not open the cluster browser"
Most often headlamp.binary — set explicitly or defaulted per OS (see installation) — names nothing that exists. Install Headlamp, or point headlamp.binary at the real path.
The same message covers every other way an open can fail: the server started but never began listening, the context named in clusters: is no longer in the kubeconfig, or the cluster credentials have lapsed and the kubeconfig's credential plugin cannot refresh them.
"AWS login did not finish in time." The Cluster button ran saml2aws login && aws eks update-kubeconfig … in a Workspace Terminal tab and it did not succeed within three minutes — a declined or missed MFA push, a wrong password, or saml2aws itself erroring. The terminal tab is left open; check it, finish or retry the login by hand, then click Cluster again.
The Docker button is disabled
The project declares no containers. That is the only thing the button can know without running docker on every project switch, so it is the only reason it ever shows. Settings will fill the section in for you — Docker → Auto-populate.
The Docker tab says Docker is not installed, or that the daemon is down
These two say what they say, and they need different fixes. Jarvis resolves docker the way it resolves aws, through a login shell's PATH: a Docker installed for your shell is one Jarvis can find, one installed only for a GUI session is not. A daemon that is not running is Docker Desktop, OrbStack or colima not started — start it and reopen the tab.
They appear inside the tab rather than on the button because finding out costs a subprocess, and the button would have to pay it every time you switched project.
A container in the Docker tab is greyed out
It is configured in docker: but Docker has no container by that name. Either the stack is down — bring it up and the row fills in — or the container was renamed, in which case fix the name in Settings. Jarvis will not remove your declaration on your behalf.
Voice does nothing
whisper.binaryPath and whisper.modelPath must both point at files that exist. If a hotkey is already taken by another app, Jarvis says so at startup rather than silently not listening.
On Linux, recording also needs ffmpeg and a working PulseAudio or PipeWire server — ffmpeg -f pulse -i default -t 2 /tmp/mic.wav is the same call Jarvis makes, and it either produces a file or names the reason.
Alt+Space does nothing, and Jarvis said so at startup
You are on Wayland. No application can register a system-wide shortcut there; the protocol does not offer one, so this is not something Jarvis can work around. echo $XDG_SESSION_TYPE confirms it.
The microphone button and the composer work exactly as they always did. To get a hotkey back, either bind one in your desktop's own keyboard settings (pointing it at the Jarvis window), or log into an Xorg session, where the shortcut registers normally.
Replies are shown but never spoken, and nothing is logged
No voice is installed that can speak them, and the message in the panel says which. On Linux both languages go through Piper, and a Piper model speaks one language — so English wants voice.piperModel and Arabic wants voice.piperArabicModel. See configuration.
Speaking also needs a player: pw-play, paplay or aplay, whichever your sound server provides. Jarvis probes for them in that order at startup.
Jarvis has no icon in the launcher, the dock or alt-tab
An AppImage does not register itself with the desktop, so there is no .desktop entry to take an icon from. The bundle carries both — see Putting Jarvis in your application launcher in installation, or install AppImageLauncher, which does it for every AppImage you run.
Running from source has no entry either, for the same reason. Electron's icon: option sets _NET_WM_ICON, which several Linux desktops ignore in favour of matching WM_CLASS against an installed .desktop file — so the launcher entry is what actually decides the icon, on both.
The AppImage will not start
Three things, in the order they bite:
libfuse.so.2: cannot open shared object file— an AppImage is a mounted filesystem and Ubuntu 22.04 and later ship FUSE 3 only.sudo apt install libfuse2t64, or run it as./Jarvis-*.AppImage --appimage-extract-and-runand skip mounting entirely.- A sandbox error naming
chrome-sandbox— run with--no-sandbox. On Ubuntu 24.04 this is AppArmor restricting unprivileged user namespaces rather than anything about the build. - It starts and the window is blank — open the devtools from the View menu (
autoHideMenuBarhides the bar; Alt reveals it) and read the console.
pnpm bootstrap fails building node-pty
It needs a C++ toolchain and Python, which the error names: build-essential and python3 on Debian and Ubuntu, gcc-c++ make python3 on Fedora, base-devel python on Arch.
This step is not optional on Linux. node-pty ships prebuilt binaries for macOS and Windows only, and every agent session and every Terminal tab is a pty.
SyntaxError: The requested module 'electron' does not provide an export named 'BrowserWindow'
ELECTRON_RUN_AS_NODE=1 is set in the environment you launched from, which tells the Electron binary to behave as plain Node — so there is no electron module to import from. Every Electron-based editor's integrated terminal sets it (VS Code, Cursor, Windsurf). env -u ELECTRON_RUN_AS_NODE pnpm start, or launch from a terminal that is not inside one.
A Terminal tab has no blocks, no file sidebar and no chips
The shell integration is bash and zsh only, and echo $SHELL says which you have. Anything else — fish, nu, dash — gets a plain working terminal with no command blocks and no completion, exactly as it did before the feature existed. That is deliberate: the hooks are per-shell syntax, and a wrapper guessing at a shell it does not know is how a user loses their PATH.
~/.bash_logout stopped running
The bash integration replaces bash -l with bash --rcfile <wrapper> -i, because bash honours --rcfile only for an interactive non-login shell — a login shell ignores it, and the hooks would never install. The wrapper reads the login files itself, in bash's own order, so the PATH and environment are the same; but the shell is not technically a login shell, so .bash_logout does not run and shopt login_shell is off.
Settings saved, nothing changed
Most settings are not applied live. Use Restart Jarvis after saving — the button appears once a save succeeds. The Remote access section is the exception: a save re-reads jarvis.yaml and applies it to the bridge at once.
Comments disappeared from jarvis.yaml
A Settings save rewrites the file. The previous version is beside it as jarvis.yaml.bak-<timestamp>.
The app looks stale after a code change
tsc alone is not the build. The renderer's vendored libraries and the icon are copied into dist/ by a script:
pnpm --filter @jarvis/desktop buildA terminal tab is gone after opening many tabs
Only hosted pages are capped (eight, each a Chromium process). Terminal and API tabs are exempt from eviction — if one disappeared, it was closed, not evicted.
Browser/phone can't connect: "unexpectedly closed the connection"
The browser says <name> unexpectedly closed the connection (ERR_CONNECTION_CLOSED), or the phone app never gets past connecting, even though Settings shows the bridge and Browser access as On.
On macOS this is usually the application firewall. It allows incoming connections per app, by the app's code signature. A build that is unsigned, ad-hoc signed or freshly rebuilt is a new app to the firewall, so it resets every connection to Jarvis's ports on the Tailscale IP (7717 for the bridge, 7718 for the browser listener) before a byte reaches Jarvis. Nothing shows in Jarvis's audit log. Connections to 127.0.0.1 are not filtered, which is why everything still works from the laptop itself. To confirm, open System Settings → Network → Firewall: if it is on, the rebuilt Jarvis is missing from Options… or is set to block.
If you can change the firewall, allow Jarvis in Firewall → Options… (or add it again after each rebuild), and try again.
On a managed Mac where the firewall can't be changed, keep Jarvis off the tailnet address and let Tailscale forward to it. tailscaled is signed by Tailscale, so the firewall lets its connections through:
In Settings → Remote access → Reachable on, open Advanced… and pick This machine only (
127.0.0.1), then save. Set this in Settings, not by hand-editingjarvis.yamlwhile Settings is open: Settings keeps its own copy of the file, and its next save writes that copy back over your edit. A hand edit is also not applied until Jarvis restarts, while a Settings save applies the Remote access section at once.Forward both ports from the tailnet to loopback:
shtailscale serve --bg --tcp 7717 tcp://127.0.0.1:7717 tailscale serve --bg --tcp 7718 tcp://127.0.0.1:7718Use your own
remote.portandremote.web.portif you changed them. This forwards raw TCP, so TLS still ends at Jarvis and the certificate the phone or browser checks is still Jarvis's own.Connect as before, by the certificate's name (
https://<machine>.<tailnet>.ts.net:7718/in a browser). This needs a pairing that carries that name — path 1. A pinned pairing dials the IP address in its link, which is now127.0.0.1, so it cannot connect this way.
Every connection now reaches Jarvis from 127.0.0.1, so that is the source the audit log shows. tailscale serve status lists what is forwarded. To undo it, turn each forward off and pick the Tailscale address in Settings again:
tailscale serve --tcp=7717 off
tailscale serve --tcp=7718 offOn Windows, claude is not recognised in a terminal
The CLI is installed somewhere PATH does not name — usually %USERPROFILE%\.local\bin, which its own installer does not always add. Add that directory to your PATH and open a new terminal: a window that was already open keeps the PATH it started with, and so does a Jarvis that was launched before the change. Jarvis itself is unaffected either way when jarvis.yaml names the full path.
On Windows, the Terminal tab has no blocks and no autocomplete
The integration is PowerShell's and needs PSReadLine, which every Windows PowerShell 5.1 and PowerShell 7 install has unless a policy removed it. If SHELL in Jarvis's environment names a real Windows path — Git's bash.exe, say — that shell is used instead and gets no integration; unset it, or point it at powershell.exe.
On Windows, recording fails naming DirectShow
Voice input records through ffmpeg's DirectShow input, so ffmpeg has to be on the PATH the app was launched with. "ffmpeg lists no DirectShow audio device" means ffmpeg ran and found no microphone — check Settings → Privacy → Microphone, and that a capture device is enabled.
On Windows, Arabic is read in an English voice
No Arabic voice is installed. Windows ships none by default: Settings → Time & language → Speech → Add voices. Jarvis prefers the voice named in voice.arabicVoice, then any voice of the language, then the system default — which is why it speaks at all rather than going silent.
On Windows, Alt+Space does nothing
Another application holds it — PowerToys Run claims it by default. Jarvis says so at startup and registers Ctrl+Shift+Space / Ctrl+Alt+Shift+Space instead, and every hint in the app then names that pair.