Skip to main content

On This Page

Debugging GitHub Actions "Pending-Forever" Silent Failures

3 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

When GitHub Actions Goes Silent: The Pending-Forever Bug I Hit Shipping My MCP Server to npm

GitHub Actions workflows for the safari-mcp server stalled indefinitely with zero jobs scheduled despite showing a “queued” status. The system provided no UI error banners, leaving releases stuck for over 125 hours. This occurred despite using standard runner labels and no deployment environments.

Why This Matters

Technical reality often diverges from UI reporting; GitHub Actions does not surface billing exhaustion errors within the run detail page, leading to “silent” failures that appear as permanent pending states. This is exacerbated by a 10x billing multiplier for macOS runners, which can deplete a standard 2,000-minute free tier in just 20 builds, potentially blocking entire CI/CD pipelines due to serialized concurrency groups.

Key Insights

  • macOS runners on GitHub Actions are charged at a 10x multiplier compared to Linux runners as of 2026.
  • Billing exhaustion for specific runner types results in a “pending” status with empty jobs and pending_deployments arrays in the GH API.
  • Concurrency groups can serialize and block new runs on available runners (like Ubuntu) if previous runs on exhausted runners (like macOS) remain in the queue.
  • The mcp-publisher tool supports non-interactive authentication using the gh auth token via the -token flag for headless environments.
  • Workflow dispatch with tag inputs allows re-triggering specific releases without deleting and recreating GitHub Release objects.

Working Examples

Adding a manual trigger with tag input to recover stuck automated releases.

on:
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag to publish (e.g. v2.9.3)"
        required: true
        type: string

Portable shell script to download architecture-specific binaries across macOS and Linux.

OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then ARCH=amd64; fi
if [ "$ARCH" = "aarch64" ]; then ARCH=arm64; fi
curl -sL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_${OS}_${ARCH}.tar.gz" -o mcp-publisher.tar.gz

Non-interactive authentication for the MCP Registry CLI using the GitHub CLI token.

GH_TOKEN=$(gh auth token)
mcp-publisher login github -token "$GH_TOKEN"
mcp-publisher publish

Practical Applications

  • Implementing workflow_dispatch with fallback logic using ${{ github.event.inputs.tag || github.ref_name }} to enable manual recovery of failed automated releases.
  • Avoiding hardcoded OS-specific binaries like ‘darwin’ in CI scripts to allow immediate switching to Linux runners during macOS billing depletion.
  • Using the GitHub CLI (gh) token as a PAT for automated publishing tools to bypass interactive browser-based logins in headless CI or local emergency environments.

References:

Continue reading

Next article

Optimizing High-Throughput Workloads with InfluxDB Time-Series Database

Related Content