Skip to content

small-tools: tldr (tealdeer) cache never installs — tldr --update fails and aborts install.sh #263

Description

@ycpss91255

Problem

small-tools/install.sh installs tldr and seeds its cache, but after a fresh
run tldr <command> does not work — it errors with:

Page cache not found. Please run `tldr --update` to download the cache.

The client actually installed on the target is tealdeer 1.6.1 (dpkg -S $(which tldr)tealdeer, /usr/bin/tldr), and the install step that is
supposed to populate the cache fails:

$ tldr --update
Could not update cache

Caused by:
    0: Could not decompress downloaded ZIP archive
    1: invalid Zip archive: Could not find central directory end
$ echo $?
1

Because this is a hard failure, the cache is never written and every page
lookup fails.

Why it also breaks the rest of the install

tldr --update is line 147 of small-tools/install.sh, and it sits inside
the long && \ chain
:

# small-tools/install.sh:145-150
# tldr update
mkdir -p /home/"${USER_NAME}"/.local/share/tldr && \
tldr --update && \                      # <- exits 1 here

# delete old tmux plugin manager, avoid problems
rm -rf /home/"${USER_NAME}"/.tmux/plugins/tpm && \
...

Since tldr --update returns 1, the && chain short-circuits and every
subsequent step is silently skipped
— tpm clone, tmux config copy,
tmux-powerline setup, etc. A cosmetic "nice to have" (tldr cache) aborts the
whole tail of the installer.

Root causes

  1. Non-fatal step treated as fatal. A failed tldr cache download should not
    abort the installer. It is chained with &&, so it does.

  2. Wrong cache directory (and an always-true guard). Lines 11-12 and 146
    operate on ~/.local/share/tldr (the old Node/C tldr client layout).
    tealdeer 1.6.1 ignores that path entirely; its real cache is
    ~/.cache/tealdeer/tldr-pages/. So the rm -rf / mkdir -p are dead no-ops
    for the client that is actually installed. Worse, the guard on line 11 is
    if [ -n "/home/${USER_NAME}/.local/share/tldr" ] — a test on a non-empty
    string literal, which is always true, so the rm -rf always runs.
    The same [ -n ... ] / [ -z ... ]-on-a-literal antipattern repeats at
    lines 15, 19, 23; these should be [ -d ... ] / [ ! -d ... ] path tests.

    $ ls -d ~/.local/share/tldr            # script touches this
    No such file or directory
    $ ls -d ~/.cache/tealdeer/tldr-pages   # tealdeer actually uses this
    /home/yunchien/.cache/tealdeer/tldr-pages
  3. Package mismatch. The apt list installs package tldr (apt-cache policy tldr → candidate 0.9.2-5), but the binary present is the separate
    tealdeer package (1.6.1). The two clients have different cache layouts and
    different update mechanics, which is why the ~/.local/share/tldr handling
    no longer matches reality.

Evidence — working manual recovery

tealdeer's own downloader produced the broken ZIP, but fetching the release
asset directly yields a valid archive, and unzipping it into the tealdeer cache
makes tldr work immediately:

curl -sSL -o /tmp/tldr.zip \
  https://github.com/tldr-pages/tldr/releases/latest/download/tldr.zip
# -> HTTP 200, 19 MB, "Zip archive data" (valid)

mkdir -p ~/.cache/tealdeer/tldr-pages
unzip -oq /tmp/tldr.zip -d ~/.cache/tealdeer/tldr-pages

tldr tar        # -> renders correctly

Secondary: fish tab-completion for tldr does not load

The tealdeer completion ships at /usr/share/fish/completions/tldr.fish, but
that directory is not part of fish's $fish_complete_path (which scans the
vendor_completions.d dirs, plus the user/etc dirs — tealdeer ships nothing
there). So tldr --<TAB> (e.g. --language) completes nothing. Sourcing the
file by hand proves the file itself is fine:

$ fish -c 'complete -C "tldr --la"'                                    # nothing
$ fish -c 'source /usr/share/fish/completions/tldr.fish; complete -C "tldr --la"'
--language	Override the language

Fix that works: copy the completion into a directory fish does scan:

mkdir -p ~/.config/fish/completions
cp /usr/share/fish/completions/tldr.fish ~/.config/fish/completions/

Proposed change

In small-tools/install.sh:

  • Decouple the cache update from the && chain so a failed download cannot
    abort the installer, e.g.:

    tldr --update || echo "WARN: tldr cache update failed; run 'tldr --update' later" >&2
  • Add a robust fallback when tldr --update fails: download the release zip
    via curl and unzip into the correct tealdeer cache dir
    (~/.cache/tealdeer/tldr-pages/).

  • Drop / fix the ~/.local/share/tldr handling (lines 11-12, 146) — it
    targets the wrong layout for tealdeer. Use ~/.cache/tealdeer/ if any
    pre-clean is needed.

  • Pin the client. Decide on tealdeer explicitly (install the tealdeer
    package, not tldr) so the cache path and update behaviour are predictable.

  • Install the fish completion to a path fish actually scans
    (~/.config/fish/completions/tldr.fish), since the snap fish ignores
    /usr/share/fish/completions.

Files in scope

  • small-tools/install.sh (lines 10-13, 87, 145-147)
  • small-tools/remove.sh (lines 44-45 mirror the wrong ~/.local/share/tldr
    path)

Notes

  • The broken-ZIP failure from tealdeer's own downloader was reproducible in this
    environment; the curl + unzip path is a reliable workaround and a good
    fallback to bake into the installer.
  • Minor doc point: tealdeer's traditional-Chinese set (pages.zh_TW, ~305
    pages) is sparse and does not include common commands like tar. For Chinese
    output tldr -L zh <cmd> (simplified) is the practical choice. Two gotchas
    worth a one-line doc note: -L is capital L (lowercase -l is --list),
    and the language code uses an underscore (zh_TW), not a hyphen
    (zh-TW). Document wherever tldr usage appears (README.adoc:477-478,
    small-tools/README.adoc:175-176, small-tools/README_zh.adoc:120-121).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions