> ## Documentation Index
> Fetch the complete documentation index at: https://docs.roboticks.io/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub App Troubleshooting

> Common failures with the Roboticks GitHub App — webhook 4xx errors, missing Check Runs, rate limits, and token expiry. Diagnosis steps and fixes.

# GitHub App Troubleshooting

Most GitHub App issues fall into four buckets: webhooks failing, Check Runs not posting, the installation in an unexpected state, or token / rate-limit problems. Work through this page in order — each section has a fast diagnostic and a fix.

<Info>
  The fastest universal diagnostic: **Roboticks dashboard → Settings → Integrations → GitHub App → Webhook log**. It shows every delivery, its HTTP response, and the downstream job. If you can't see a delivery for an action you just took, the issue is between GitHub and us; if you can see it but the job didn't run, the issue is downstream.
</Info>

## Webhook returns 4xx

### Symptom

In GitHub: **Settings → Applications → Roboticks → Advanced → Recent Deliveries** shows deliveries with red 401 / 403 / 422 status codes.

### Diagnosis

| Status                     | Likely cause                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized`         | HMAC verification failed — our copy of the webhook secret no longer matches yours.                            |
| `403 Forbidden`            | The installation was deleted or the repo was removed from it.                                                 |
| `422 Unprocessable Entity` | Payload schema we don't recognise — usually an event we never subscribed to that GitHub is delivering anyway. |
| `5xx`                      | A transient platform issue on our side. GitHub will retry 8 times over \~8 hours.                             |

### Fix

<AccordionGroup>
  <Accordion title="401 — webhook secret mismatch">
    1. Roboticks dashboard → **Settings → Integrations → GitHub App** → click **Rotate webhook secret**. Rotation is atomic — old deliveries in flight fail, new deliveries verify with the new secret.
    2. GitHub re-signs subsequent webhooks with the new secret automatically; no manual step on the GitHub side.
    3. Click **Redeliver** on the failed events in the GitHub delivery view to replay them.
  </Accordion>

  <Accordion title="403 — installation or repo removed">
    1. Confirm the App is still installed in **GitHub → Settings → Applications → Installed GitHub Apps**.
    2. Confirm the repo is in scope: **Roboticks → Configure → Repository access**.
    3. If the install or repo is gone, re-install per [Installation](/github-app/installation) — historical data is retained.
  </Accordion>

  <Accordion title="422 — unrecognised payload">
    Safe to ignore. We acknowledge with 422 to make GitHub stop retrying an event we don't handle. If the same event repeats and you want it handled, open a ticket — it's probably a new GitHub event we should add to the [subscription list](/github-app/webhooks#subscribed-events).
  </Accordion>

  <Accordion title="5xx — our side">
    Check [status.roboticks.io](https://status.roboticks.io). If no incident is posted and the failures persist for >5 minutes, file a ticket; include the `X-GitHub-Delivery` UUID from a failed delivery so we can find it in our trace store.
  </Accordion>
</AccordionGroup>

## Check Run never posts

### Symptom

A PR is opened, but no **Roboticks** check appears in the Checks tab — not even `queued`.

### Diagnosis

Walk these four checks in order:

<Steps>
  <Step title="Is the App installed on this repo?">
    GitHub → repo → **Settings → Branches** (or any settings page) → scroll to the App badge in the sidebar. If Roboticks isn't there, install per [Installation](/github-app/installation).
  </Step>

  <Step title="Is the installation suspended?">
    GitHub → **Settings → Applications → Installed GitHub Apps → Roboticks**. A red **Suspended** badge means the org admin paused the App. Click **Unsuspend**. Suspended installs receive no webhooks until unsuspended.
  </Step>

  <Step title="Is the repo linked to a Roboticks project?">
    Roboticks dashboard → **Settings → Repositories**. If the repo shows **Connected but not linked**, click **Link to project**. Webhooks for an unlinked repo are acknowledged but skipped (visible in the webhook log with reason `no_project`).
  </Step>

  <Step title="Did the PR match the project's policy?">
    Default policy skips drafts and forks. **Settings → Project → Check Run policy** toggles these. Drafts that were marked ready-for-review will trigger a run on the `ready_for_review` event.
  </Step>
</Steps>

If all four pass and the Check Run still doesn't post: the dashboard **Run log** will show the job and the failure reason. If it shows nothing at all, file a ticket with the PR URL and we'll trace it.

## Check Run posted, but `conclusion = action_required`

This is by design when a human-in-the-loop step is pending. The most common cases:

* **Requirements PDF awaiting review** — go to **Requirements → Pending review** in the dashboard, accept or edit the LLM-extracted requirements, and the next push will re-evaluate.
* **Standards subscription update** — a pinned standard published an amendment that touches requirements in this PR. Review the diff at **Standards → Updates**.

`action_required` does not block merge unless your branch protection lists Roboticks as required.

## Check Run posted, but `conclusion = neutral` on every PR

This usually means the test job ran but no JUnit XML was found, or no `@confirms(...)` decorators were detected.

### Fix

1. In the dashboard **Run log**, open the latest run → **Artifacts** tab. If the JUnit file is missing or empty, your test command isn't emitting JUnit — see [Writing tests](/testing/writing-tests-pytest).
2. If JUnit is present but no requirements are linked, run `pytest -p roboticks.pytest_plugin -v` locally and confirm the plugin loads. The plugin is auto-registered when `roboticks` is installed, but if a wrapper script overrides the Python environment it may be skipped.

## Rate limit exceeded

### Symptom

The webhook log shows successful deliveries, but jobs sit in `queued` for minutes or the dashboard shows `GitHub API: 403 rate limit exceeded`.

### Diagnosis

GitHub Apps have a per-installation rate budget that scales with the number of repositories. Three causes:

| Cause                                    | Fix                                                                                                 |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------- |
| Burst — many PRs opened at once          | Wait. The budget refills hourly. Jobs queue and dispatch as budget returns; no Check Runs are lost. |
| Long-running script polling `GET /pulls` | Move it onto webhooks. Polling is the #1 cause of installation rate exhaustion.                     |
| Many `Re-run all jobs` clicks            | Each one issues a fresh check-runs POST + log uploads. Avoid scripting it.                          |

We monitor headroom per installation and warn at 75% / page at 95% — you'll see a banner in the dashboard before a hard failure.

## Token expiry

You should never see a token-expiry error in normal operation. If you do:

```
GitHub API: 401 Bad credentials (installation token expired)
```

It means the backend's installation-token cache is stale — usually after a multi-region failover. The fix is automatic: the backend re-mints a token on the next call and retries the failed request once. You'll see a short blip in the run timeline but the job completes.

If you see this error **persistently** (>5 minutes), file a ticket immediately — it indicates the App private key is unreachable.

## Repo was renamed or transferred

GitHub fires `repository.renamed` / `repository.transferred` events. We update the project ↔ repo mapping automatically — no manual step. The first push or PR after the rename will run cleanly.

<Warning>
  Transfers across **GitHub accounts** (e.g. from a personal account to an org) are treated as an uninstall on the old account and a fresh install on the new one. The App must be re-installed on the destination account and the repo re-linked to the project.
</Warning>

## Still stuck

<CardGroup cols={2}>
  <Card title="Status page" icon="signal" href="https://status.roboticks.io">
    Live incident status.
  </Card>

  <Card title="Open a ticket" icon="envelope" href="mailto:hello@roboticks.io">
    Include the `X-GitHub-Delivery` UUID and PR URL for fastest triage.
  </Card>

  <Card title="Webhooks reference" icon="bolt" href="/github-app/webhooks">
    Re-read the event handling rules.
  </Card>

  <Card title="Check Run reference" icon="circle-check" href="/github-app/check-runs">
    Conclusion semantics and re-run paths.
  </Card>
</CardGroup>
