ErrLookup › Background articles › HTTPError: what it means when a library throws an "HTTPError" (and how to fix it)

HTTPError: what it means when a library throws an "HTTPError" (and how to fix it)

"HTTPError" is the generic exception name many open-source libraries use to wrap any failed HTTP request — a non-2xx status, a failed retry loop, or an upstream service error rethrown in the library's own words. Developers meet it in Budibase, Bundler, yt-dlp, frp, and others whenever an HTTP call behind an SDK, importer, or fetcher fails and the library surfaces the failure as an HTTPError instead of a raw network exception.

Distilled from 332 documented records across 11 repositories.

Background

HTTPError is not one error but a naming convention: across these repositories it is the exception type a library raises when an HTTP request it made fails. The layer that produces it is usually a thin wrapper over a real HTTP client — Node fetch in Budibase's server, urllib or Bundler's Gem::Net::HTTP fetcher, the fetch() calls in frp's web dashboard, urllib in yt-dlp's networking stack. The wrapper inspects the response, decides it is not acceptable (non-2xx status, ok:false payload, missing context), and raises HTTPError, often carrying the upstream status code and sometimes the raw response body as the message.

What the caller sees varies widely because each library chooses what to embed. Some pass through the upstream text: yt-dlp's "HTTP Error {status}: {reason}", frp's bare "HTTP {status}", and Budibase's Gemini File Search wrapper, whose message is literally the upstream response body. Others use the message for their own validation result and use the HTTP status purely as a transport code — a large share of the Budibase records are HTTP 400 errors about request-shape problems (invalid datetime formats, missing workspaceId, malformed project-package manifests, non-UUID Teams appIds), not transport failures at all. In those cases HTTPError is best read as "the API rejected your request" rather than "the network broke".

A few records use the type for subtler jobs. nexu-io/open-design raises "Request failed with no error details" as a defensive tail of a retry loop — control fell through without any stored last_error, which usually means the retry count was below 1 or an exception type was not covered by the except handlers. Bundler's "Too many redirects" is a redirect-limit guard: the fetcher recurses on redirect responses until a configured hop limit is hit. Budibase deliberately throws a 404 (not 403) for "Agent log detail not found" so callers cannot probe for other agents' log entries — the HTTP status on the HTTPError is part of the library's intended semantics, so read it before deciding how to react.

Because the message text is so library-specific, the durable debugging approach is shared: capture the exception object, not just the string. Several libraries attach structured fields — yt-dlp exposes .status, .reason, .response, and .redirect_loop; frp's wrapper sets err.status; Budibase embeds upstream status codes in the message. Recovering those fields (and the response body where the stream is kept open, as yt-dlp's adapter does) is almost always the fastest route from "HTTPError" to the real cause.

Common causes

What usually fixes it

Go deeper

Documented occurrences

…and 312 more across the corpus — use search.

Honest provenance: generated on 2026-08-29 from AI-assisted analysis of the linked records. See how records are made.