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
- 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
- Re-run the tool in a fresh process after fixing credentials or connectivity; a new process starts with an unpoisoned mutex
- 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
- Treat the first panic in the log as the real bug — this lock error only appears after `fetch_issue_labels` panicked while holding the mutex
- Make `fetch_issue_labels` return `Result` instead of panicking on network, token, or rate-limit failures
- Run the changelog tool locally with a valid `GITHUB_TOKEN` before relying on CI to generate it
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
- only structs are supported
- missing `type Input`
- missing `type Context`
- missing `async fn resolve`
- string literals must not contain more than one class (hint:
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/088499fcc4ce7f9b.
Report an issue: GitHub.