Skip to main content

Enterprise Server 3.22 is currently available as a release candidate.

Troubleshooting live migrations from GitHub Enterprise Server to GHE.com

Advice for problems you may encounter with your migration.

If your migration encounters a problem, check the migration status with gh elm migration status --migration-id MIGRATION-ID and review the error information.

StatusMeaningRecommended action
CreatedThe migration has been created but not yet startedRun gh elm migration start
QueuedThe migration is waiting to startWait
ExportingData is being exported from the sourceMonitor with gh elm migration status
ProcessingExported data is being imported to the destinationMonitor with gh elm migration status
Ready for cutoverThe initial migration is complete and the migration is ready for cutoverWhen ready, run gh elm migration cutover
Cutting overThe source repository is archived and remaining changes are being applied to the destinationMonitor; the status will transition to Completed
CompletedThe migration has finished successfullyVerify the destination repository and reclaim mannequins
FailedThe migration encountered an unrecoverable failureInvestigate the error (see below)
PausedThe migration is pausedCheck the pause reason and resolve (see below)
TerminatedThe migration was cancelledN/A
DegradedThe destination is unreachableCheck network connectivity between the GitHub Enterprise Server appliance and GHE.com (see below)

Migration status is "Failed"

A migration enters the Failed status when an unrecoverable error prevents it from continuing. This is distinct from individual resources failing to import—a failed migration means the migration itself cannot proceed.

To investigate, run gh elm migration status --migration-id MIGRATION-ID and review the error details in the response. Each failure includes a correlation ID in the format (Correlation ID for Support: UUID). If you contact GitHub Support, provide this ID so the support team can investigate.

After resolving the underlying issue, abort the failed migration with gh elm migration cancel --migration-id MIGRATION-ID and start a new migration.

Migration status is "Paused"

A migration enters the Paused status when an issue requires your intervention before it can continue. Run gh elm migration status --migration-id MIGRATION-ID and check the pause reason.

Common pause reasons:

  • Credential expiry: One of the personal access tokens (classic) has expired. Create a new token with the required scopes and update it with gh elm credential update. Then restart the migration.
  • Rate limiting: The migration hit API rate limits. Wait a few minutes, then restart.

To restart a paused migration after resolving the underlying issue:

gh elm migration start --migration-id MIGRATION-ID

Migration status is "Degraded"

A Degraded status means the migration service on the GitHub Enterprise Server appliance cannot reach the destination enterprise. The migration continues on the source side, but the destination status is unknown.

Check network connectivity between the GitHub Enterprise Server appliance and your subdomain of GHE.com, then run gh elm migration status --migration-id MIGRATION-ID again. The status response includes a timestamp for the last successful contact with the destination, which can help you assess how long the connectivity issue has been occurring.

Migration stuck in "Exporting"

If your migration remains in the Exporting status with no progress change for 30 minutes or more, the exporter may be stuck.

  1. Run gh elm migration status --migration-id MIGRATION-ID and note whether resource counts are changing.

  2. If counts are static, check the appliance's network connectivity to the destination.

  3. Review exporter logs on the GitHub Enterprise Server appliance (requires SSH admin access):

    Shell
    journalctl -t elm-exporter-backfiller --since "1 hour ago" | tail -50
    journalctl -t elm-exporter-sender --since "1 hour ago" | tail -50
    
  4. If the exporter task has crashed, it should recover automatically. If it does not, contact GitHub Support.

Git synchronization not completing

If gh elm migration status shows that the initial Git push has not completed after an extended period, check the Git syncer logs:

Shell
journalctl -t elm-exporter-git-syncer --since "2 hours ago"

Look for:

  • connection refused: A network issue between the GitHub Enterprise Server appliance and the destination. Check firewall rules and DNS resolution.
  • authentication failed: The personal access token (classic) may lack the required scopes or may have expired.
  • remote: error: The destination may be rejecting the push. Contact GitHub Support with the error details.

Some resources failed to import

Individual resources can fail to import without causing the overall migration to fail. You can see a count of failed resources in the output of gh elm migration status --migration-id MIGRATION-ID.

Failed resources are only shown after all automatic retries have been exhausted, so any failures you see are confirmed as unresolvable without intervention. Review the error details in the status response: each failed resource in backfill or live updates will display "state": "failed".

If the number and types of failed resources are acceptable, you can proceed with cutover. If not, abort the migration, resolve the underlying issue, then start a new migration.

Cutover failed and the source repository is unavailable

If a cutover fails after the source repository has been archived, the ELM service will attempt to unarchive the repository. If this fails, a repository administrator can unarchive the repository. See Archiving repositories.

Be aware that unarchiving a repository will cause additional load on the instance, as all issues and pull requests in the repository will be reindexed in Elasticsearch.

After the source repository is unarchived, you can either retry cutover using gh elm migration cutover --migration-id MIGRATION-ID, or abort the migration with gh elm migration cancel --migration-id MIGRATION-ID and start a new migration when you're ready.

Migration must be restarted due to a force push

If someone force-pushes to the default branch of the source repository while a migration is in progress, the Git synchronization between the source and destination breaks. Force pushes rewrite commit history in a way that cannot be reconciled incrementally.

If this happens, abort the migration with gh elm migration cancel --migration-id MIGRATION-ID and start a new migration. Before restarting, communicate to your team that force pushes to the default branch are not permitted while a migration is active.

Migration access token was rejected

If your migration fails with an authentication error, check that:

  • Both the source and destination tokens are personal access tokens (classic). Fine-grained personal access tokens are not supported.
  • If the destination organization enforces SAML single sign-on, the token must be authorized for SSO.
  • Both tokens have the scopes specified in Migrating your repository with Enterprise Live Migrations.

If you recently rotated a token, the migration picks up new credentials automatically. You do not need to run ghe-config-apply or restart the migration service.

GitHub CLI access token was rejected

Enterprise Live Migrations uses two sets of credentials. This section applies to the operator tokens created in step 2 and stored locally by gh elm configure.

The operator must use a personal access token (classic) for each endpoint:

  • The source operator token must be created on GitHub Enterprise Server.
  • The target operator token must be created on GHE.com.
  • Both tokens have the scopes specified in Migrating your repository with Enterprise Live Migrations.
  • The token owner must be an administrator of the corresponding enterprise. Selecting a scope does not grant the user administrative access.
  • Fine-grained personal access tokens are not supported.

Common responses

ResponseMeaningRemedy
401 Bad credentialsThe endpoint could not authenticate the token. Authorization scopes have not been evaluated yet.Check that the token has not expired or been revoked, that it was copied completely, and that the source and target tokens were not exchanged. Confirm that each token was created on the host where it is being used.
403 ForbiddenThe token was authenticated, but its user or scopes do not authorize the operation.Use a personal access token (classic) with admin:enterprise. Confirm that the token owner is an administrator of the enterprise. If SAML SSO applies, authorize the token for SSO.
Resource not accessible by personal access tokenThe token type or permissions are unsupported. This commonly occurs with a fine-grained personal access token.Replace it with a personal access token (classic) that has admin:enterprise.
404 Not FoundThe request may be using the wrong API URL, or Enterprise Live Migrations may not be enabled for the destination enterprise.For GHE.com, use the tenant API URL, such as https://api.SUBDOMAIN.ghe.com, without a trailing slash. Verify the source API URL as well. If both URLs are correct, contact GitHub Support to confirm that Enterprise Live Migrations is enabled.

Validate the tokens independently

Test each token against the /user endpoint before using it with Enterprise Live Migrations. These commands print response headers but discard the response body.

For the source (GitHub Enterprise Server) token:

curl --silent --show-error --output /dev/null --dump-header - \
  --header "Authorization: Bearer $SOURCE_OPERATOR_TOKEN" \
  "$SOURCE_API_URL/user"

For the target token:

curl --silent --show-error --output /dev/null --dump-header - \
  --header "Authorization: Bearer $TARGET_OPERATOR_TOKEN" \
  "$TARGET_API_URL/user"

Each request should return 200 OK. The X-OAuth-Scopes response header should include admin:enterprise.

If /user returns 200 OK but an Enterprise Live Migrations command returns 401 Bad credentials, the CLI may have a different token or URL stored. Run gh elm configure again and carefully associate each token with its corresponding endpoint.

Operator tokens are stored locally by the Enterprise Live Migrations CLI. After rotating an operator token, run gh elm configure again or supply the replacement credentials using the appropriate command-line options.

This differs from the migration service tokens configured in step 4. Updated migration service credentials are picked up automatically and do not require ghe-config-apply or a migration-service restart.

Do not include access tokens in logs, screenshots, support bundles, or support requests. If the problem continues, provide GitHub Support with the HTTP status, endpoint hostname, migration ID, timestamp with timezone, and any correlation ID—but not the token.

The source GHES URL was rejected

Enterprise Live Migrations requires the GitHub Enterprise Server URL to use HTTPS. If the URL is configured with HTTP, the migration will fail preflight validation.

Collecting logs for support

When contacting GitHub Support, the most useful artifacts are:

  1. A support bundle (preferred): Run ghe-support-bundle -u on the GitHub Enterprise Server appliance. This captures all Enterprise Live Migrations logs automatically.
  2. Migration status output: gh elm migration status --migration-id MIGRATION-ID
  3. The migration ID and approximate time of failure (with timezone)
  4. Any correlation IDs from error messages

If a support bundle is not possible, you can collect logs manually:

Shell
journalctl -t elm-exporter-migration-manager --since "24 hours ago" > migration-manager.log
journalctl -t elm-exporter-backfiller --since "24 hours ago" > backfiller.log
journalctl -t elm-exporter-sender --since "24 hours ago" > sender.log
journalctl -t elm-exporter-git-syncer --since "24 hours ago" > git-syncer.log