Skip to documentation
MMirageDocs

Documentation

Reference

Troubleshooting

Fix setup problems, unavailable machines, queued jobs, and unexpected fallback runs.

My repository is missing or unavailable

  1. Select the repository’s GitHub account in Mirage’s account menu.
  2. In Settings, use Manage access on GitHub and confirm the repository is selected for the Mirage App.
  3. Return to Mirage and select Sync repositories or Sync repository details.
  4. Confirm it is a private, unarchived repository. Public repositories cannot use Mirage execution.
  5. Use Retry provisioning if setup reports an error. Private repositories selected in GitHub do not need a separate Mirage switch.

If you cannot change these settings, ask an owner of the GitHub organization. Mirage roles follow GitHub: only organization owners manage settings.

My Mac is connected but not ready

Open the Mac in Machines and check the individual runner profile. A connection means Mirage can reach the host; it does not mean every runner environment is ready.

What to checkWhat to do
Image download or preparationWait for preparation and its self-test. If it fails, read the profile’s error and Next step.
Insufficient disk or memoryFree space or reduce the configured runner resources. Image preparation needs room beyond the job’s writable disk budget.
Paused, on battery, or under loadResume the host, connect power, and allow resource pressure to settle.
Linux x64 unavailableCheck that Rosetta is installed and the x64 self-test passes.
macOS unavailableCheck that the profile is enabled and its image is prepared. Older GUI-bridge installations need the current signed host package; pause and drain before rerunning bootstrap.
Offline after rebootCheck the network and power. FileVault may need a person to unlock the disk; native macOS jobs also need a desktop login.

Use mirage host doctor on the Mac for the detailed checks. See Use the CLI if the command is not found.

My job stays queued

GitHub shows a waiting job as queued without a reason. Mirage combines its reports in one Mirage check per commit. In the repository's GitHub check setting, choose Always, After 5 minutes, After 15 minutes (the default), Custom, or Never. The delay controls the first waiting report; infrastructure failures appear immediately unless reporting is Never.

The check explains why jobs haven't started, what to do, and what Mirage does when the repository's queue timeout ends. Workflows, matrix jobs and reruns update the same check. Waiting completes as neutral once no job is waiting, even if jobs are now running. Source infrastructure failures report failure; superseded attempts stay in history. Its details link opens Runs in Mirage.

If the check doesn’t explain the wait:

  1. Confirm GitHub App access and repository provisioning finished.
  2. Compare the workflow’s runs-on label with the supported runner labels.
  3. Check Machines for a machine available to the selected account. Confirm the required profile is Ready and has headroom for the job’s allocation.
  4. Check the machine’s Available to list and any capacity grant needed by the account.
  5. Check GitHub for an Actions outage and confirm Mirage’s dashboard is reachable.

If you need to unblock CI while Mirage is unavailable, restore the job’s original GitHub-hosted label and push the workflow. For a workflow already using the attempt expression, cancelling and manually rerunning it in GitHub selects the hosted label on the next attempt. Check for side effects before rerunning a workflow.

My job ran on GitHub instead of my Mac

Open the job in Mirage and inspect its route reason and attempt number. Common causes are:

  • No machine took the job within the repository’s queue timeout: the Mac was busy, paused, asleep, on battery, or short of resources. Check or change the timeout on the repository’s page in Repos.
  • The required runner profile was not ready or startup failed.
  • The global emergency switch was active, the repository was disconnected or ineligible, or the event did not meet Mirage's trust checks.
  • The workflow was manually rerun and its attempt expression selected GitHub.

Fix the reported cause and trigger a new workflow run to try local execution again. Re-running an existing run keeps its later attempt number and will still select the hosted fallback with the documented expression.

My job failed after waiting for a machine

A job on a literal mirage-* label has no fallback. When no machine takes it within the repository’s queue timeout, Mirage adds a failed Mirage check that says how long it waited, then cancels the run. Open the check’s details for the explanation, next steps, and links to the workflow and machines. To fix it:

  • Make a machine available. In Machines, check for one whose profile is Ready, that isn’t paused, and that lists the account under Available to.
  • If jobs often wait, add a machine, increase its background work budget, or request smaller runners.
  • If long waits are expected, raise the timeout on the repository’s page in Repos.
  • If the job should run on GitHub instead, use the attempt expression so it falls back.

Rerun the workflow once a machine can take the job.

Fallback did not run

Check for a literal runs-on: mirage-* label. A literal label targets Mirage on every attempt. For hosted fallback, use the full expression:

Linux x64 with hosted fallback
runs-on: ${{ github.run_attempt == '1' && 'mirage-linux-x64' || 'ubuntu-24.04' }}

Automatic fallback also requires the GitHub App to retain access and Mirage to be reachable to request the rerun. Direct Cloudflare jobs do not have automatic fallback. A normal failed test does not trigger fallback either; inspect its logs in GitHub.

If attempt 2 does not start on GitHub’s runner, check whether a spending limit or budget is blocking GitHub-hosted runners. See When GitHub-hosted runners are blocked.

My job ran out of disk

A step that fails with No space left on device usually means the runner’s disk filled up, not that your code is wrong. When a Linux job on a Mac fails with its disk at least 97% full, Mirage says so: Runs shows Out of disk beside the job, and a failed Mirage check on the commit says how much of the disk the job used and where it failed.

Each Linux job on a Mac gets its own disk, the size of the job’s disk allocation (6 GiB unless you change it). The runner image and a swap file sit on that disk too, so your steps have less than the budget. The job’s Disk panel in Runs shows its peak use against the disk.

To fix it:

  • Raise the job’s disk allocation under Job routes in Repos. The Mac needs that much free space for each job it runs at once, within its background work budget.
  • Or have the job write less: delete build outputs and caches it no longer needs, and prune Docker images it pulled.
  • For a Cloudflare job, choose a larger runner size.

To rerun these jobs elsewhere instead, open the repository in Repos and set When a job runs out of disk to Fall back. Mirage then reruns the job once on its fallback runner rather than reporting it. A job a setup pull request routes reruns on its original runner; a job using the attempt expression reruns its whole workflow, whose next attempt runs on GitHub. A job with a literal mirage-* label has no fallback, so Mirage reports it either way, as it does when the attempt that ran out of disk already was the fallback. An ordinary test failure never falls back.

Mirage recognizes a full disk only on a Mac’s Linux jobs, where each job’s disk is its own and its size is the budget. Jobs on a Linux host’s Docker runtime, on Proxmox, in macOS VMs and on Cloudflare fail as usual; read the failed step’s log in GitHub.

Cloudflare or a provider comparison is unavailable

For Cloudflare, check that the repository’s Cloudflare switch is on and the selected Shared or BYO backend is ready. Shared mode needs access enabled by Mirage; BYO setup failures show an error in Settings. Docker-dependent jobs need a different provider.

For comparisons, confirm the onboarding PR is merged and the job’s configuration is applied. Refresh job discovery if the workflow changed, approve any requested GitHub App permissions, and read the provider’s unavailable reason. Only eligible completed jobs can start an experiment. See Compare CI providers for the supported workflow shapes.

Collect diagnostics

Record the GitHub run and job links, repository and account, attempt number, runner label, and Mirage’s route reason. For a host problem, include the machine’s Mirage version and the affected profile’s readiness message.

On the affected Mac · requires the Mirage CLI
mirage host status
mirage host doctor
mirage host diagnostics --lines 80

Share those details with the person administering Mirage for your team when asking for help. For a test failure, include the relevant GitHub step output. Review any diagnostics before sharing them, and leave out secrets, tokens, and pairing codes.