Metadata
Version: 5.0.3 (also reproduced on 5.0.0 from Homebrew)
OS: macOS 15 (arm64)
Shell: zsh / sh
Anime: any
Describe the bug
When anidb_curl fails at the network level — timeout, connection reset, empty body — anidb_search returns an empty string and the caller reports No results found!. That message tells the user their search term matched nothing, when in fact the site was never reached.
The Cloudflare guard in anidb_search only catches one specific failure shape:
_page="$(anidb_curl "$(printf "$search_api" "$1")" | tr '\n' ' ' | sed 's|<a href|\n<a href|g')"
if printf "%s" "$_page" | grep -qi "Just a moment"; then
[ "$curl_exe" = "curl" ] && die "Blocked by cloudflare. Try installing curl-impersonate"
die "Blocked by cloudflare."
fi
It matches the body string Just a moment. If curl exits non-zero and prints nothing — --max-time 10 expiring is the common case — $_page is empty, the check does not fire, and execution reaches:
anime_list=$(anidb_search "$query")
[ -z "$anime_list" ] && die "No results found!"
So a site outage, a dropped connection, a DNS failure and a genuinely unknown anime all produce the same message.
Steps to reproduce
I hit this against the live anidb.app outage in #1877, where the HTML routes time out with 0 bytes while the JSON API still answers 200, and every search prints No results found!. Full route-by-route measurements are in #1877 (comment).
It reproduces deterministically by pointing the host at a blackhole address so the request times out the same way:
printf '198.51.100.1 anidb.app\n' | sudo tee -a /etc/hosts
ani-cli naruto
# -> "No results found!" after ~10s (--max-time 10 expiring), no hint that the host was unreachable
The underlying curl behaviour, without editing /etc/hosts:
$ curl -sL --max-time 10 --resolve anidb.app:443:198.51.100.1 "https://anidb.app/browse?q=x" -o /dev/null
$ echo $?
28 # timed out, empty stdout -> empty $_page -> "No results found!"
A refused connection takes the same path, just faster (exit 7, empty output). Remember to remove the /etc/hosts line afterwards.
Expected behavior
A network failure should say so. Something like Connection error: could not reach https://anidb.app lets the user tell "the site is down" apart from "no anime by that name", which is currently guesswork.
Suggested fix
The smallest change is an empty-response check right after the fetch, since an empty page is never a valid response here:
anidb_search() {
#shellcheck disable=SC2059
_page="$(anidb_curl "$(printf "$search_api" "$1")" | tr '\n' ' ' | sed 's|<a href|\n<a href|g')"
[ -z "$_page" ] && die "Connection error: no response from $base_api"
if printf "%s" "$_page" | grep -qi "Just a moment"; then
...
Note that propagating curl's exit status instead does not work as-is: anidb_curl runs inside a command substitution, so a die there exits only the subshell and the parent continues with an empty $_page. Checking the captured value in the caller avoids that.
anidb_desc, anidb_episodes and the m3u8 fetch use the same anidb_curl pattern and have the same blind spot, so the check is probably worth applying there too — anidb_episodes returning empty currently surfaces as an episode-selection failure rather than a network error.
This is filed separately from #1877 on purpose: that one is the anidb.app outage itself, which resolves on its own, while this is about the message ani-cli shows whenever any network failure happens. Happy to send a PR if you want it in this shape.
Metadata
Version: 5.0.3 (also reproduced on 5.0.0 from Homebrew)
OS: macOS 15 (arm64)
Shell: zsh / sh
Anime: any
Describe the bug
When
anidb_curlfails at the network level — timeout, connection reset, empty body —anidb_searchreturns an empty string and the caller reportsNo results found!. That message tells the user their search term matched nothing, when in fact the site was never reached.The Cloudflare guard in
anidb_searchonly catches one specific failure shape:It matches the body string
Just a moment. If curl exits non-zero and prints nothing —--max-time 10expiring is the common case —$_pageis empty, the check does not fire, and execution reaches:So a site outage, a dropped connection, a DNS failure and a genuinely unknown anime all produce the same message.
Steps to reproduce
I hit this against the live anidb.app outage in #1877, where the HTML routes time out with 0 bytes while the JSON API still answers 200, and every search prints
No results found!. Full route-by-route measurements are in #1877 (comment).It reproduces deterministically by pointing the host at a blackhole address so the request times out the same way:
The underlying curl behaviour, without editing /etc/hosts:
A refused connection takes the same path, just faster (
exit 7, empty output). Remember to remove the /etc/hosts line afterwards.Expected behavior
A network failure should say so. Something like
Connection error: could not reach https://anidb.applets the user tell "the site is down" apart from "no anime by that name", which is currently guesswork.Suggested fix
The smallest change is an empty-response check right after the fetch, since an empty page is never a valid response here:
Note that propagating curl's exit status instead does not work as-is:
anidb_curlruns inside a command substitution, so adiethere exits only the subshell and the parent continues with an empty$_page. Checking the captured value in the caller avoids that.anidb_desc,anidb_episodesand the m3u8 fetch use the sameanidb_curlpattern and have the same blind spot, so the check is probably worth applying there too —anidb_episodesreturning empty currently surfaces as an episode-selection failure rather than a network error.This is filed separately from #1877 on purpose: that one is the anidb.app outage itself, which resolves on its own, while this is about the message ani-cli shows whenever any network failure happens. Happy to send a PR if you want it in this shape.