Skip to content

Troubleshooting

Fixes for problems that are not configuration mistakes. A configuration Doppel refuses reports why and where; this page is for the cases where nothing is reported because nothing got far enough to report it.

Installing

macOS refuses to run the downloaded binary

"doppel" cannot be opened because the developer cannot be verified.

or, from a shell:

zsh: killed     doppel

macOS attaches com.apple.quarantine to anything a browser downloads, and Gatekeeper refuses a quarantined binary that is not signed with an Apple Developer ID. The releases are not signed or notarized, so a copy downloaded through a browser is rejected. The file is not damaged.

Clear the attribute:

xattr -d com.apple.quarantine ~/Downloads/doppel

Confirm that was the cause:

xattr -l ~/Downloads/doppel | grep quarantine

On Apple Silicon, if it still will not run after that -- an arm64 binary needs at least an ad-hoc signature -- re-sign it locally and clear the attribute again:

codesign --force --sign - ~/Downloads/doppel
xattr -d com.apple.quarantine ~/Downloads/doppel

Avoiding it entirely: the one-line installer downloads with curl, which does not set the attribute. Nothing needs clearing after it.

doppel: command not found after installing

The install directory is not on PATH. The installer prints which shell profile it appended to; either open a new shell or source that file:

source ~/.zshrc

If it reported that it could not find a profile, add the directory yourself:

export PATH="$HOME/.local/bin:$PATH"

The installer says there is no prebuilt binary

Three platforms are built: macOS on Apple Silicon, and Linux on x86-64 and arm64. Anywhere else, build from source -- the workspace is pure Rust and needs no system libraries:

cargo install --path crates/doppel-cli

Running

cannot bind 127.0.0.1:8080: Address already in use

Something already holds the port. Find it:

lsof -nP -iTCP:8080 -sTCP:LISTEN

A previous doppel that did not shut down cleanly is the usual answer.

Permission denied binding a port below 1024

Ports 1 to 1023 need elevated privilege. Doppel warns about one at startup rather than refusing it, because running behind a capability or a redirect is a legitimate deployment -- but if it was a typo, this is the error it produces.

On Linux, grant the capability instead of running as root:

sudo setcap 'cap_net_bind_service=+ep' "$(command -v doppel)"

the database schema is not ready

The PostgreSQL store refuses to serve against an unmigrated schema rather than altering it at startup. Apply the migrations, which is a separate, deliberate step:

doppel config migrate --database-url "$DOPPEL_DATABASE_URL"

doppel config migrate --status reports what is applied without changing anything. See Storing configuration in PostgreSQL.

control socket directory ... does not exist

control.socket names a path whose parent directory is not there. Doppel creates the socket, not the directory above it -- creating directories a configuration names would let a typo silently produce a socket nobody is looking for.

A reload says sections need a restart

note: these sections changed but only take effect after a restart: server, admin

The listeners those sections describe are already bound. admin.tokens and admin.access do take effect on reload; the host, the port and admin.enable do not. See Changing configuration while it runs.

The admin API

Every request answers 401

The token is not one the running configuration knows. Two common causes:

  • It was written into the configuration file but not reloaded. Authorization is judged against what the last reload put into force, deliberately -- see the admin API.
  • It is shadowed by DOPPEL_ADMIN_TOKENS. A token name claimed by the environment replaces the configured one entirely; startup logs a warning naming each one shadowed. See Tokens from the environment.

A write answers 409

Someone changed that proxy between your read and your write. Read it again, reapply the change, and retry with the new revision -- do not drop the If-Match header, which is what makes the collision visible at all.

token add says the name is supplied by the environment

A token issued under a name the environment already claims would never authenticate, because the environment is searched first. Pick another name, or remove it from DOPPEL_ADMIN_TOKENS.


Anything not covered here is worth an issue on the tracker.

The dashboard

The admin root answers 503

DASHBOARD_NOT_BUILT. This binary was compiled without the dashboard's static assets -- a source build that skipped the frontend. Released binaries and the published image always carry it.

npm --prefix frontend ci && npm --prefix frontend run build
cargo build --release -p doppel-cli

The order is the whole answer: the assets are embedded at compile time, so building them without rebuilding the binary changes nothing about what it serves. If Node is not available and the JSON API is enough, admin.dashboard: false stops the route being served at all, which is a clearer answer than a 503.

The page loads but every button is disabled

The caller has no rights to spend. The dashboard asks GET /api/v1/access what it may do and disables what the server would refuse; the tooltip on each control says so. Enter a token, or check admin.access -- the same two causes as a 401 above, since it is the same decision.

A change made elsewhere is not on screen

It will be within a minute: the list refetches on a timer, and the timer is paused while the tab is hidden. Switching back to the tab refetches immediately.