Troubleshooting
When something fails, start with den doctor: it checks the tools, the AWS profiles, the
logins and the local ports den.yaml needs, and prints the command that fixes each gap.
Add --deep to also ask SSM whether each bastion is online. The Logs panel (L) and
the service’s own log show what den ran and what it answered.
Each entry below says what you see, why it happens and what to do, and links to the page that goes deeper. Errors specific to one data store are in the Troubleshooting section of its page: RDS, ElastiCache, DocumentDB, Redshift, OpenSearch, Neptune.
AWS and the tunnel
The SSO login has expired
You see: ExpiredToken, Unable to locate credentials, SSO login expired, a service
that fails at once with an AWS error, a secret that is not ready, or an update check that
fails right after start.
Why: the AWS SSO token behind a profile lasts a few hours. den cannot refresh it, and every command it runs as that profile fails the same way.
Fix: log in again from den’s AWS panel (Enter on the session), or with
aws sso login --profile P. Secrets and services become ready by themselves afterwards;
press c again for an update check. den doctor reports an expired session as a
warning. See AWS SSO.
The Session Manager plugin is missing
You see: the service log shows the AWS CLI’s SessionManagerPlugin is not found, and
den doctor fails session-manager-plugin.
Why: an SSM port-forward is run by the AWS CLI, which hands the session to a separate plugin. Without it the CLI starts and stops at once.
Fix: den doctor prints the install command for your OS and package manager; run it,
then run den doctor again. The commands for every platform are in
Installing what den needs.
The local port is already in use
You see: port 5555 is already in use — is another ssh/tunnel still running? for a
tunnel, a service that never reaches CONNECTED, or den doctor warning ports in use
or local ports (two services share a port).
Why: a tunnel is ready when its local port accepts connections, so something else
holding the port, often a den you left running or an old ssh -L, either blocks the
tunnel or answers in its place. Two services with the same local_port cannot be
connected at once.
Fix: find the holder with lsof -i :PORT (on Windows netstat -ano) and stop it, or
give the service another local_port. See Configuration reference.
The forward drops after a while
You see: Your session timed out due to inactivity and has been terminated. in the
log, a tunnel that worked and now refuses connections, or an EC2 Instance Connect tunnel
that closes after a time.
Why: SSM closes an idle port-forward, and EC2 Instance Connect tunnels are time-limited. Open connections end with it.
Fix: set reconnect: true on the service (or press a on it to toggle it): den
reopens the forward after a drop, and the credential is renewed while connected either
way. See DocumentDB › Auto-reconnect and
Transports.
TargetNotConnected
You see: the SSM session fails with TargetNotConnected.
Why: the bastion’s SSM agent is offline, or ec2_instance_id names an instance in
another account or region than the profile and aws_region_code.
Fix: den doctor --deep asks SSM whether each bastion is online. Check the instance
ID, the profile and the region of the environment. See
Environments.
Permission denied (publickey)
You see: the log of an ssh transport or an SSH tunnel ends in
Permission denied (publickey).
Why: ssh found no usable key, and den cannot answer a password prompt.
Fix: load the key into your agent (ssh-add) or name it in the transport’s args
(-i ~/.ssh/key). See Transports and Tunnel.
Credentials and clients
The tunnel is up but the store refuses the login
You see: PAM authentication failed or Access denied (RDS), WRONGPASS invalid username-password pair (ElastiCache, MemoryDB), password authentication failed for user "IAMR:…" (Redshift), AccessDenied on GetClusterCredentialsWithIAM.
Why: the tunnel and the credential are fine and the store rejected it. The usual
causes are a missing IAM permission (rds-db:connect, elasticache:Connect,
memorydb:Connect, the Redshift credential actions), the database user not set up for IAM
authentication, or a token minted as a different profile than the one granted: the store
checks credential_profile, not aws_profile.
Fix: grant the credential_profile identity the permission on the right resource, and
check the user’s side (GRANT rds_iam TO …, an iam authentication mode). The prerequisites
list on each store’s page names the exact grants. For MemoryDB make sure memorydb: true
is set, since a token signed for the wrong service is rejected.
The tunnel is up but no data comes back
You see: the client connects and then hangs or errors: MongoServerSelectionError: Server selection timed out, MOVED 10.x.x.x:6379, a mysql client that ignores the tunnel,
a kubectl forward that gets no answer.
Why: one tunnel reaches one address. DocumentDB’s driver discovers the replica set and
then tries the in-VPC hostnames, a cluster-mode cache answers keys on other shards with
MOVED to addresses only the VPC can reach, localhost makes the mysql client use a Unix
socket instead of the tunnel, and a kubectl resource that is not itself serving the
store’s port has nothing to forward to.
Fix: use the connect command den copies (y) rather than writing your own: it carries
directConnection=true, -h 127.0.0.1 and the right TLS options. Do not use redis-cli -c
through a tunnel. For kubectl, put a TCP proxy in front of the store inside the cluster.
See DocumentDB,
ElastiCache and Transports.
A client stops working after a while
You see: a client that reconnects by itself fails with a login error it did not have before.
Why: an IAM token is checked when a connection opens, and lives 15 minutes. den re-mints it every 13 minutes while the tunnel is up and writes it where the client looks, but a client that reuses the old one on its own reconnect has an expired token.
Fix: open a new connection, or press r in the detail view to mint a token now and y
to copy the command again. Open sessions keep working.
The terminal shows empty boxes instead of icons
You see: or empty boxes in the menu and the service list.
Why: den draws its icons with Nerd Font glyphs, and the terminal’s font has none.
Fix: install a Nerd Font (brew install --cask font-jetbrains-mono-nerd-font) and set
the terminal’s font to it. See Quickstart.
VPN
openfortivpn is too old for SAML
You see: WARN: Bad key in configuration file: "saml-login", then
VPN account password: and ERROR: Could not authenticate to gateway, or without the
helper unrecognized option '--saml-login'.
Why: openfortivpn older than 1.23.0 has no SAML login. Ubuntu 24.04 and older, Debian 12 and older and RHEL 9 ship one.
Fix: upgrade it. den doctor --for vpn prints the package command, or the steps to
build it from source where no package is new enough; then run den vpn install-helper
again. See VPN › Troubleshooting.
The kernel has no PPP (WSL)
You see: the SAML login works, then Couldn't open the /dev/ppp device, Please load the ppp_generic kernel module and The kernel does not support PPP; den stops openfortivpn and
shows the cause. den doctor fails or warns kernel PPP.
Why: the VPN’s pppd needs a PPP driver. The kernel of WSL 3.0.1 is built without one, and
on other Linux kernels the module may not be loaded, or its files were removed by an upgrade
since boot. Creating /dev/ppp by hand does not help.
Fix: on WSL 3.0.1 roll WSL back to 2.7.14, or use FortiClient on Windows. Elsewhere,
sudo modprobe ppp_generic, or reboot after a kernel upgrade. See
VPN › Linux kernel and WSL.
The gateway answers Forbidden
You see: the SAML page says Forbidden … /remote/saml/start.
Why: the gateway counts too many sessions for your account, often stray openfortivpn processes left by earlier failed logins.
Fix: sudo pkill -x openfortivpn and sudo pkill -x pppd clear them, the live one
included; then connect again. See VPN › Leaked sessions.
Install and updates
The update fails its checksum
You see: checksum mismatch for den_…: got …, want … in the install steps of the
Updates panel, or from install.sh / install.ps1.
Why: the downloaded archive is not the one the release’s checksums.txt describes: the
download was damaged, or it was altered.
Fix: nothing is installed, and the running den is untouched. Run the install again; if
it repeats, report it, and do not install the archive by hand. A release that publishes no
checksums.txt installs with a warning that the download was not verified. See
Updates and Install.
den cannot write the update
You see: the install fails with a permission error.
Why: den replaces its binary with a rename next to it, so a den under a root-owned directory cannot update itself.
Fix: use the commands the Updates panel prints, or reinstall into a folder you own
(--dir). See Updates.
den is not found, or is an older one
You see: command not found after the install, or den --version shows a version older
than the one you installed.
Why: the install folder is not on PATH, or another den earlier on PATH shadows the
new one. On Windows, the PATH change reaches only terminals opened afterwards.
Fix: add the folder the installer printed to your shell’s startup file and open a new terminal; remove the older copy the installer names. See Install.
A tool is installed but den cannot use it
You see: den doctor reports a tool as off PATH or too old, or aws stays at v1 after
installing v2.
Why: Homebrew installs libpq and mysql-client keg-only, so they are on disk but not on
PATH. A package manager keeps the version a distribution shipped. A v1 AWS CLI from pip
sits in ~/.local/bin, which Ubuntu puts first.
Fix: follow the steps den doctor prints for your machine (brew link --force …,
python3 -m pip uninstall -y awscli, a source build), then run hash -r and den doctor
again. See den doctor.
Config, panels and agents
den.yaml is not applied, or a key is ignored
You see: a panel that lacks the service you added, an error with a file:line, or a
warning in the Config panel naming a key.
Why: den loads the first file it finds (-c, ./den.yaml, ~/.config/den/den.yaml), which
may not be the one you edited. A file with errors is not applied when reloaded; an unknown key
is a warning and is ignored.
Fix: the Config panel shows the path den loaded and every problem. Fix the lines it lists, or check the key against the configuration reference. With the JSON Schema in your editor a misspelt key is underlined as you type (den.yaml schema). See Editing den.yaml.
unknown env
You see: service[0] "x": unknown env "y" or runbook "x": unknown env "y".
Why: env: names an environment that is not under environments:. Names are
case-sensitive.
Fix: correct the name or add the environment. See Environments.
A runbook is missing or cannot reach the database
You see: a runbook that does not appear in the panel, or a script that cannot connect to the database.
Why: the panel’s warnings name the reason for a missing runbook: an unknown key, an unknown
env, a name that clashes, or an env_map that does not map the source’s environment. A
script finds the tunnel through DEN_PORT_*, which exist only for services connected in the
running dashboard.
Fix: press w in the Runbooks panel to read the warnings; connect the service before
running the runbook. See Runbooks and
Runbook sources.
An agent cannot connect a production service
You see: a connect through den mcp is refused, or the agent sees no services.
Why: production services need mcp.allow_production: true and then your confirmation in the
MCP client for each connect, so a client that cannot ask you (no elicitation support) is
refused. mcp.allow patterns match whole names, and a pattern that matches none hides everything.
Fix: use a client with elicitation support, and check the patterns. See den mcp and Security model.