epi052/feroxbuster · warning
JSON has no tag_name
Error message
JSON has no tag_name: {json_response} What it means
check_for_updates fetches the latest GitHub release metadata as JSON and extracts the `tag_name` field to compare against the current version. If the parsed JSON object has no string `tag_name` field, the function cannot determine the latest version and bails with this error. It guards against GitHub (or a proxy/mirror) returning a response that is valid JSON but not a release object.
Solutions
- Wait for the GitHub API rate limit to reset or set a GITHUB_TOKEN, since rate-limit responses lack tag_name
- Verify the update-check URL points at a GitHub releases API endpoint (e.g. /repos/OWNER/REPO/releases/latest) that returns a release object
- Inspect the JSON echoed in the error message to confirm what was actually returned and adjust the source/proxy accordingly
- Ignore the error — it only affects the update banner and is reported as an unknown update state, not a fatal condition
Example fix
// before: raw JSON checked directly let latest_version = json_response["tag_name"].as_str()...; // after: defensive check by caller let status = check_for_updates().unwrap_or(UpdateStatus::Unknown);
Defensive patterns
Strategy: fallback
Validate before calling
if let Ok(v) = serde_json::from_str::<serde_json::Value>(&body) {
if v["tag_name"].as_str().is_none() {
eprintln!("update check: response has no tag_name");
}
} Type guard
fn has_tag_name(v: &serde_json::Value) -> bool { v["tag_name"].as_str().is_some() } Try / catch
match check_for_updates() {
Ok(status) => status,
Err(e) => { log::warn!("update check failed: {e}"); UpdateStatus::Unknown }
} Prevention
- Use the official GitHub releases API endpoint for the update check URL
- Handle GitHub API rate-limit responses (403 with JSON error body) explicitly
- Treat update-check failures as non-fatal and surface an 'unknown' update state
- Log the offending JSON body so misconfigured URLs are easy to diagnose
When it happens
Trigger: Calling check_for_updates (or triggering the banner update check at startup) when the HTTP endpoint returns JSON lacking a `tag_name` key — e.g. a GitHub API rate-limit/error JSON body, a non-release endpoint, or a self-hosted update URL that returns `null` or `{}`.
Common situations: GitHub API rate limiting (403 JSON body without tag_name), configuring a custom update-check URL that points at a non-release JSON document, network middleboxes (corporate proxies) rewriting the response, or GitHub changing/omitting tag_name for draft releases.
Related errors
- [ ] Unable to download wordlist from url
- Empty --request-file file provided
- Invalid request: Missing head/body separator
- Invalid request: Missing request line
- Invalid request: Empty request line
AI-assisted analysis of epi052/feroxbuster@1f595dab5c (2026-09-13).
Data as JSON: /api/errors/660f8d3cb56f6f59.
Report an issue: GitHub.
Appendix: source
Thrown at src/banner/container.rs:616
let result = make_request(
&client,
&api_url,
DEFAULT_METHOD,
None,
level,
&handles.config,
tx_stats,
)
.await?;
let body = result.text().await?;
let json_response: Value = serde_json::from_str(&body)?;
let latest_version = match json_response["tag_name"].as_str() {
Some(tag) => tag.trim_start_matches('v'),
None => {
bail!("JSON has no tag_name: {json_response}");
}
};
// if we've gotten this far, we have a string in the form of X.X.X where X is a number
// all that's left is to compare the current version with the version found above
if latest_version == self.version {
// there's really only two possible outcomes if we accept that the tag conforms to
// the X.X.X pattern:
// 1. the version strings match, meaning we're up to date
// 2. the version strings do not match, meaning we're out of date
//
// except for developers working on this code, nobody should ever be in a situation
// where they have a version greater than the latest tagged release
self.update_status = UpdateStatus::UpToDate;
} else {
self.update_status = UpdateStatus::OutOfDate;
}View on GitHub (pinned to 1f595dab5c)