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

  1. Wait for the GitHub API rate limit to reset or set a GITHUB_TOKEN, since rate-limit responses lack tag_name
  2. Verify the update-check URL points at a GitHub releases API endpoint (e.g. /repos/OWNER/REPO/releases/latest) that returns a release object
  3. Inspect the JSON echoed in the error message to confirm what was actually returned and adjust the source/proxy accordingly
  4. 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

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


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)