Guides

Troubleshooting

The errors uxd actually prints, what each one means, and the shortest fix — starting with uxd doctor.

Start with doctor

uxd doctor
OK   git version: git 2.50.1
OK   gh (github cli): authenticated
OK   config dir: ~/.uxd
OK   state dir: ~/.local/state/uxd
OK   project my-project: config: schema-valid
OK   project my-project: repo: bare repo at ~/dev/uxd/my-project/repo
OK   project my-project: fetch refspec: remote.origin.fetch configured

Each line is one check, prefixed OK, WARN, or FAIL. OK needs nothing. WARN is survivable — that project still works, one feature is degraded. FAIL means something is broken, and doctor exits non-zero if any check fails.

doctor covers: git version, gh presence and auth, config-dir readability, state-dir writability, stale locks, and per project — schema validity, the bare repo and its fetch refspec, the editor binary on PATH, configured commands that shadow built-in verbs, core.hooksPath, and worktree/state drift.

Errors by code

Every failure prints one line to stderr, an optional hint:, and exits with a code you can branch on. See Exit codes.

E_CONFIG — exit 3

error(E_CONFIG): unknown project 'nope'
hint: known projects: demo-app

The project has no ~/.uxd/<name>.toml. List what uxd can see with uxd projects, or create one with uxd setup.

For a file that exists but does not parse, check it in isolation:

uxd config validate
→ all project configs valid

config validate names the offending key and file when it fails. uxd config path prints which directory is actually in use — worth checking when you have UXD_CONFIG_DIR set and forgot.

E_RESOLVE — exit 4

error(E_RESOLVE): branch 'does-not-exist' does not exist on origin
hint: check the name, or push the ref first

uxd fetched and the ref is not there. Usually a typo, or a branch that only exists locally in your main clone. Push it, or point at a sha instead. See Refs for the full resolution order.

E_GIT — exit 5

A git or gh command failed. The underlying error is printed with it. Common causes: no network on a first checkout (partial clones fetch lazily), a missing remote.origin.fetch refspec (doctor reports it and prints the exact git config line to run), or authentication.

E_SETUP — exit 6

A setup step or a hook exited non-zero. The failing command is echoed. Fix the command, then force setup to run again on the existing workspace:

uxd my-project feat/login checkout --setup
→ worktree ready (reused)
→ running setup
installing deps

E_USAGE — exit 2

Bad flags or a missing argument. The hint lists what was expected:

error(E_USAGE): unsupported shell 'ksh'
hint: one of: bash, zsh, fish

Common situations

warning: skipping feat-login: worktree is dirty (use --force)
The worktree has uncommitted changes and uxd will not throw them away. Commit or stash them, or pass --force if you genuinely want them gone.
SLUG        KIND    BRANCH      STATUS   PORT  AGE  LAST USED
feat-login  branch  feat/login  missing  3053  2m   1m
The directory was deleted outside uxd. Drop the stale state entry:
uxd my-project clean --prune-state --yes
Git allows one worktree per branch. uxd detects this and points you at the existing workspace rather than failing obscurely — use that workspace, or check out the sha instead of the branch name.
doctor warns when core.hooksPath is set. Relative hook paths resolve incorrectly from a worktree, and pnpm install may install hooks into the bare repo. uxd does not modify your repository — see Known caveats.
Ports are allocated deterministically from the slug, then scanned upward if the block is taken. If something outside uxd holds the port, raise base_port in the project config or override once with --port. See Run dev servers in parallel.

Seeing more

-v / --verbose echoes every external command uxd runs, prefixed with · on stderr:

uxd my-project feat/login checkout -v
→ fetching origin/feat/login
· git -C ~/dev/uxd/my-project/repo fetch origin feat/login --no-tags
· git -C ~/dev/uxd/my-project/repo worktree add ~/dev/uxd/my-project/trees/feat-login -B feat/login --track origin/feat/login
→ worktree ready: ~/dev/uxd/my-project/trees/feat-login

-q / --quiet does the opposite — it suppresses the step logs so only the result is printed.

Pair --verbose with --dry-run to inspect a plan without executing it:

uxd my-project feat/login run dev --dry-run