yewstack/yew · error · anyhow::Error

Failed to lock GITHUB_ISSUE_LABELS_FETCHER: {err}

Error message

Failed to lock GITHUB_ISSUE_LABELS_FETCHER: {err}

What it means

The Yew changelog tool caches a `GitHubIssueLabelsFetcher` behind a global `Mutex` (create_log_line.rs:13-14). `Mutex::lock` only fails when a previous thread panicked while holding that lock, and this code converts the `PoisonError` into an anyhow error with the shown message. The lock error is therefore always a follow-on symptom: the real failure is an earlier panic inside `fetch_issue_labels` (network error, bad token, rate limit, deserialization) in the same process.

Source

Thrown at tools/changelog/src/create_log_line.rs:76

            return Ok(None);
        }
    };

    let match_to_be_stripped = captures.get(0).ok_or_else(|| {
        anyhow!("Failed to capture first group - issue part of the message like \" (#2263)\"")
    })?;
    let mut message = commit_first_line.clone();
    message.replace_range(match_to_be_stripped.range(), "");

    let issue_id = captures
        .get(1)
        .ok_or_else(|| anyhow!("Failed to capture second group - issue id like \"2263\""))?
        .as_str()
        .to_string();

    let issue_labels = GITHUB_ISSUE_LABELS_FETCHER
        .lock()
        .map_err(|err| anyhow!("Failed to lock GITHUB_ISSUE_LABELS_FETCHER: {err}"))?
        .fetch_issue_labels(issue_id.clone(), token)
        .with_context(|| format!("Could not find GitHub labels for issue: {issue_id}"))?;

    let is_issue_for_this_package = issue_labels
        .iter()
        .any(|label| package_labels.contains(&label.as_str()));

    if !is_issue_for_this_package {
        println!("Issue {issue_id} is not for {package_labels:?} packages");
        let leftovers = issue_labels.iter().filter(|label| {
            !(label.starts_with("A-") || *label == "documentation" || *label == "meta")
        });
        let count = leftovers.count();
        if count > 0 {
            println!(
                "Potentially invalidly labeled issue: {issue_id}. Neither A-* (area), documentation nor meta labels found. \
            inspect/re-tag at https://github.com/yewstack/yew/issues/{issue_id}"
            );

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Scroll up in the output and fix the FIRST panic — it names the actual cause (auth, rate limit, network); the lock error is only fallout
  2. Re-run the tool in a fresh process after fixing credentials or connectivity; a new process starts with an unpoisoned mutex
  3. As a maintainer, make `fetch_issue_labels` return `Result` instead of panicking, or recover with `.unwrap_or_else(|p| p.into_inner())` so one bad fetch cannot poison the whole run

Example fix

// before (tools/changelog/src/create_log_line.rs)
let issue_labels = GITHUB_ISSUE_LABELS_FETCHER
    .lock()
    .map_err(|err| anyhow!("Failed to lock GITHUB_ISSUE_LABELS_FETCHER: {err}"))?
    .fetch_issue_labels(issue_id.clone(), token)?;

// after — recover the inner guard from a poisoned lock instead of aborting
let mut fetcher = GITHUB_ISSUE_LABELS_FETCHER
    .lock()
    .unwrap_or_else(|poisoned| poisoned.into_inner());
let issue_labels = fetcher
    .fetch_issue_labels(issue_id.clone(), token)?;
Defensive patterns

Strategy: fallback

Try / catch

// Rust has no try/catch; match on the lock result and recover the inner guard:
let mut fetcher = GITHUB_ISSUE_LABELS_FETCHER
    .lock()
    .unwrap_or_else(|poisoned| poisoned.into_inner());
// The data the mutex guards is a stateless fetcher, so the lock itself
// carries no invariants — using into_inner() is safe here. The original
// panic (earlier in the log) remains the bug to fix.

Prevention

When it happens

Trigger: Running `create_log_lines` over a commit range where an earlier `fetch_issue_labels` call panicked while holding `GITHUB_ISSUE_LABELS_FETCHER`; every subsequent commit processed by the same process then fails at the `.lock()` in create_log_line.rs:74-76.

Common situations: Changelog generation in CI with an expired or missing `GITHUB_TOKEN` (the API call panics first, then poisons the mutex), GitHub rate limiting during a large release run, or a transient network drop mid-run that turns every later commit into this lock error.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/088499fcc4ce7f9b. Report an issue: GitHub.