Repository navigation
Troubleshooting
Start with shelf doctor. It checks the version, the shell and its version, the config, git when git plugins are configured, and the lock, then prints No problems found or the first thing that failed.
When doctor passes but behavior is odd, escalate in this order.
-
shelf statustells you whether the lock matches the installed git revisions.revision X, want Ymeans upstream moved or someone checked out a different commit locally.shelf update --lockaccepts the new revision,shelf lock --reinstallrestores the pinned one. -
shelf info NAMEtells you what the lock actually selected. Wrong or emptyfilesexplains a plugin that installs but does nothing. -
shelf --verbose sourceshows the path it took.Unlockedmeans it rendered the existing lock without relocking. Absent, it relocked, and the per-pluginRendered,Inlined, andRemovedlines show what changed. - Re-run with the lock removed only as a last resort,
rm "$(shelf path | awk -F= '/^lock_file/{print $2}')", thenshelf lock. Usually step 3 already tells you what changed.
Reading the lock output. Loaded N plugins <config> is the config parse. Per-plugin Checked means the source was examined, Frozen means it was skipped on purpose, Skipped means the active profile excludes it. Locked N plugins <lock> closes the run. With --verbose, Unlocked is the fast path, Rendered and Inlined are per-plugin render results, and Removed is an install the config no longer owns.
Common failures and what they mean:
| Message | Cause | Fix |
|---|---|---|
plugin "x" must have exactly one source |
Two source keys, or none | Keep exactly one of github, git, remote, local, inline, ... |
plugin "x" can only set optional for a local source |
optional on a git plugin |
optional only pairs with local
|
plugin "x" has invalid remote URL |
remote without scheme or host |
Use an absolute https:// URL |
plugin "x" proto "..." must be git, https, or ssh |
Bad proto value |
One of https, git, ssh
|
plugin "x" can only set proto for forge sources |
proto on git or remote
|
Forge keys only, git URLs carry their own transport |
unknown template: NAME |
apply names a template that does not exist |
Fix the name or define it in [templates], then shelf lock
|
invalid pattern: ... |
Broken use or ignore glob |
Fix the glob, it is validated even when nothing matches |
select plugin "x" file "y": no such file |
file points at a missing file |
Check dir, or drop file and use use
|
no editor configured |
shelf edit with no editor set |
Export SHELF_EDITOR, VISUAL, or EDITOR
|
--force requires --update or --reinstall |
Bare --force
|
Attach it to --update or --reinstall
|
NAME cannot be combined with --interactive |
Both arguments to remove
|
Pick one |
unsupported shell "..." in SHELF_SHELL |
Env var set to something else |
bash or zsh only |
git is required for configured Git plugins |
git missing from PATH
|
Install git |
zsh is not installed |
Config shell absent from PATH
|
Install it or change shell
|
plugin "x" cannot set <field> for an inline plugin |
Source-specific field on inline
|
Inline takes only hooks, profiles, frozen
|
plugin "x" can only set cloneopts and depth for git sources |
cloneopts or depth on remote/local
|
Only git-backed sources clone |
plugin "x" has an empty cloneopt |
Empty string in cloneopts
|
Remove the empty entry |
plugin "x" depth must be 0 or greater |
Negative depth
|
0 means full history |
plugin "x" has an empty build command |
Empty string in build
|
Remove the empty entry |
plugin name "x" may only contain letters, digits, dashes, and underscores |
Bad name passed to add/remove
|
Letters, digits, -, _
|
invalid environment variable "x" |
Bad [env] key |
Letter or _ first, then letters, digits, _
|
unsupported shell: "x" |
shell is not bash or zsh |
One of the two |
dir "x" escapes the plugin source directory |
dir climbs out with ..
|
Keep dir inside the source |
unknown template value "x" / template value "x" has no field "y"
|
Typo in a template | Use ?. when the lookup may miss |
unknown template function "x" / unknown template filter "x"
|
Name that does not exist | Only nl and get exist |
nl takes one argument / get takes two arguments
|
Wrong template arity | Fix the call |
compile template "x": ... |
Broken {% %} block |
Check quotes, endfor, endif
|
git source "x" is not a URL / has no repository path
|
Bad git value |
Full URL or path with a repo part |
remote source "x" has no host |
remote without a host |
Absolute https:// URL |
local source: ... |
Missing path without optional
|
Fix the path or set optional = true
|
build plugin "x": command "c": ... |
Build command exited non-zero | The command output sits above the error |
decode config: ... |
TOML syntax error | The message names the position |
home directory is empty |
No HOME and no directory flags |
Set HOME or pass --config-dir/--data-dir
|
Nothing destructive happens from a failed command. Shelf validates before it writes, and downloaded or generated content goes through a temporary file plus an atomic rename, so an interrupted run does not leave a half-written lock behind.