Troubleshooting Git Deployments: Stuck, Failed or Not Triggering
Updated November 2, 2026 · 9 min read
A Git deployment can go wrong in a few different ways: stuck in progress, failing partway through, or simply not starting when you push. Each one has a different fix. When a deploy fails, the notice on the Deployments page tells you why, and the deployment logs give you the detail.
Start with the deployment logs
Before trying anything else, open the site’s deployment logs from the Deployments page in the site menu. They show which stage failed — cloning the repository, running the build, or starting the app — and that determines which section below applies.
If the latest deploy failed, read the failure notice on that page first. It names the failed step and shows the part of the output around the first error, so you often won’t need the full log.
See why a deploy failed
When a deploy of a Git site fails, xCloud shows the notice Deploys of this site are failing on the site’s Deployments page, above the list of deployments. The notice stays until a deploy succeeds.
Step 1: Open the Deployments page
Open the site and click Deployments in the site menu. You can also click View Deployments in the failure email.

Expected result: the notice appears below the summary of the latest deployment. If there is no notice, check the status of the latest deployment in the list. If it shows Failed and there is no notice, the deploy may not have reached the server: see When a deploy never reached the server.
Step 2: Read the notice
The notice tells you what went wrong and where it stopped.
| Part of the notice | What it tells you |
|---|---|
| Summary | The cause in plain words. |
| Failed step | Where the deploy stopped: Pull latest code, Deploy script, Build or Start. It is left out when no step can be named. |
| failing since | How long the site has been failing. |
| failed 2 more times with the same reason | How many more times the same failure happened. It appears only after a repeat. |
| Output lines | About 40 lines of output around the first error. Values that look like passwords and keys are hidden. |
The summary comes from matching the output against known errors, so an earlier warning can point it at the wrong cause. If the summary and the output disagree, go by the error line just above the point where the deploy stopped.
Step 3: Fix the cause and deploy again
Use the failed step to choose the fix:
| Failed step | Where to look |
|---|---|
| Pull latest code | Clone fails |
| Deploy script | The command named in the summary or in the last error lines of the output. Edit it under Deploy Script on the site’s Git page. |
| Build or Start | Build or start fails |
Then click Deploy Now at the top of the page. If you see Check & Deploy instead, click that. On the free plan there is no Deploy Now button, so push a commit to the site’s branch (Enable push to deploy must be on in the site’s Git settings), or change a setting on that page and click Save and deploy.
Expected result: the notice goes away once the deploy succeeds. xCloud does not send an alert when a site recovers. If the deploy fails again, the notice stays and shows the new result.
If the summary says only “The deploy failed.”
This means the cause is not in your site’s code or settings, so the notice shows no output lines and the alerts leave out the cause. Contact our support team and tell them which site is affected.
Deploy failure alerts
Your team hears about a failing site by email and through any notification channel you have connected.
| Where | What the alert includes |
|---|---|
| The subject Deployment Failed, the summary, the failed step, the output lines and a View Deployments button. For the full log, open the Deployments page. | |
| Slack, Telegram, WhatsApp and in-app alerts | The summary, the failed step, up to 10 lines of the cause and a link to the site’s Deployments page. |
You are told when something changes, not on every repeat:
| What happens | Do you get an alert? |
|---|---|
| A site starts failing | Yes |
| It fails again for the same reason | No, the count in the notice goes up |
| It fails with a different kind of error | Yes |
| The same kind of failure has a new reason | Yes, opening with “The deploy failed for a new reason.” At most once an hour per site |
| A deploy succeeds | No, the notice goes away |
To connect a channel or choose what you receive, see Slack, Telegram, WhatsApp and turning off notifications.
When a deploy never reached the server
A deploy that could not reach the server does not count against your site, because nothing ran there. You get no failure alert, and this attempt adds no failure notice. If an earlier deploy was already failing, its notice stays. The attempt still shows as Failed in the Deployments list, and its log says “Nothing ran on the server”.
Instead, xCloud tries the same deploy again after 2 minutes, then 5, then 8, which is 15 minutes in all. If you or a push start a newer deploy in the meantime, it replaces the retry.
If the third retry can’t reach the server either, your team gets one server disconnected notice, at most once per server in 6 hours. Check that the server is online and connected, then deploy again.
Stuck “in progress”
If a deployment still shows in progress after about five minutes, it’s likely hung rather than genuinely still running. Use the site’s Check & Deploy action: it checks whether the previous deployment process has actually stopped. If it has, xCloud marks that attempt as failed, releases the deployment lock, and starts a fresh deployment.
A deploy waiting on a retry looks different: between tries, the Deployments list shows the attempt as Failed with no new failure notice, for up to 15 minutes. See When a deploy never reached the server.
Clone fails
A failed clone falls into one of three categories, and they need different fixes:
- Missing branch — the log shows something like “Remote branch … not found.” Fix: set the deployment to point at a branch that actually exists in the repository.
- Access error — the log shows “Permission denied (publickey)” or “repository not found.” This is not a branch problem, and changing the branch will not fix it. Fix the deploy key or reconnect the Git provider instead (see below).
- Network error with no Git-specific message — retry the deployment once. If it fails again the same way, the problem is the server’s outbound connection to the Git host, not the repository or credentials.
Fixing a missing or rejected deploy key
- Open the site’s Git settings.
- Click the button to configure the deploy key.
- If xCloud can add the key to the repository automatically, it will. If it can’t (for example, you don’t have admin rights on the repository), copy the public key it shows you and add it to the repository yourself as a read-only deploy key.
- Click Verify connection.
- Redeploy.
Confirm the server can reach the Git host over SSH on port 22 — a network block there produces the same kind of access error as a bad key.
Build or start fails
.envfile path points at a folder, not a file. The path is joined to/var/www/<site>/and needs to resolve to an actual file —.envfor a normal project, or something likebackend/.envfor a monorepo. Pointing it at a bare folder name such asbackendfails with an error like “Is a directory.”- Build commands. Check the build command for typos, a missing dependency install step, or a script that assumes a different working directory than the one xCloud runs it from.
- Deploy script. If the failed step is Deploy script, see Deploy script stopped at a failed command.
Deploy script stopped at a failed command
New Git sites stop the deploy script at the first command that fails and mark the deployment as failed. This keeps a half-finished deploy from showing up as a success. The switch that controls it is Stop the deployment when a command fails.
The script only runs when Run this script after every site deployment is on.
| Site | What happens when a command fails |
|---|---|
| Created on xCloud v2.8.8 or later | The switch is on. The deploy stops at that command. |
| Created before v2.8.8 | The switch is off. The script carries on to the end, and a failed command in the middle doesn’t fail the deployment. |
| Cloned from another site | The clone copies the switch from the site it came from. |
Turn the setting on or off
If your site was created before v2.8.8, check your script first. A command that has been failing unnoticed will stop the deploy once the switch is on.
Step 1: Open your site and click Git in the site menu. The Git Settings page opens.

Step 2: Under Deploy Script, turn Stop the deployment when a command fails on or off.

Step 3: Click Save Changes. xCloud shows “Git settings updated successfully.” The change applies from the next deployment. To deploy straight away, click Save and deploy instead.
Find the command that failed
Step 1: Click Deployments in the site menu. After a failed deploy, the Deploys of this site are failing notice names the line, the command and its exit code.
Step 2: Select the failed deployment in the list. The panel shows which step failed, such as Deploy script. Click Jump to line and the line number shown on the button (for example, Jump to line 12) to go to the error in the log. The failing lines are highlighted:
XCLOUD_DEPLOY_SCRIPT_FAILED: line 2: exit 127: ./scripts/clear-cache.sh
ERROR: the deploy script failed for example.com (exit 127).

The line number counts from the top of your Deploy Script field. The shell’s own error just above it can show a number one higher, so go by the XCLOUD_DEPLOY_SCRIPT_FAILED line.
If your script starts with a set line, such as set -e, the XCLOUD_DEPLOY_SCRIPT_FAILED line doesn’t appear. Look at the last output from your script in the log instead.
Step 3: Fix the command, then click Save and deploy on the Git Settings page. The new deployment appears in the list as successful once every step finishes.
If the fix is in your repository, push it. The push starts a deployment when Enable push to deploy is on. On paid plans you can also click Deploy Now.
What your site runs after a stopped deploy
xCloud pulls your code before it runs the deploy script, so the new files are already in the site folder. A Node.js site keeps its current build only if the script stopped before your build command ran. If the build finished first, your site’s files have already changed. A site that serves files straight from the folder, such as a PHP site, can pick up those files right away, so fix the script and redeploy soon. The Deployments page may still say your site is live on the previous version, but on these sites the new files are already in place.
Write a script that handles failures
Use these patterns when a command is allowed to fail:
| You want | Write |
|---|---|
| One command may fail | ./scripts/clear-cache.sh || true |
| A step runs only when a file exists | if [ -f ./scripts/seed.sh ]; then ./scripts/seed.sh; fi |
| The whole script handles failures itself | set +e or set -e as the first line |
For example, this script allows the cache step to fail and skips the seed step when the file is missing. Any other failed command still stops the deploy:
npm install
./scripts/clear-cache.sh || true
if [ -f ./scripts/seed.sh ]; then
./scripts/seed.sh
fi
npm run build --if-present
Keep these in mind:
- Only use
|| trueon optional steps. On a required step, it hides the failure you want to see. - If the first command in your script is a
setline, the switch no longer stops the script. Blank lines and comments above it don’t change this. Your script decides what happens when a command fails. Withset +e, a failed command doesn’t stop the deploy. If the last command in the script fails, the deployment is still marked as failed. - Any
setline at the top counts, evenset -x. A script that starts withset -xno longer stops at a failed command. If the last command in the script fails, the deployment is still marked as failed. - You only see
XCLOUD_DEPLOY_SCRIPT_FAILEDwhen the switch stops the script. It doesn’t appear when your script starts withset -e, even though the script still stops at a failed command. - When the switch is on and your script has no
setline at the top, a failure anywhere in a pipeline counts. Innpm test | tee test.log, the deploy stops ifnpm testfails, even thoughteesucceeds. If you start withset -e, add-o pipefailto get the same result. - Some commands exit with an error when they find nothing. For example,
grepfails when there’s no match. Add|| trueif that’s a normal result.
For developers
The Public API exposes this switch as deploy_script_fail_fast on /api/v1/sites/{uuid}/deploy-config. See Deploy Git Projects with the Public API and MCP.
Auto-deploy not triggering on push
If pushes to the branch aren’t kicking off a deployment at all:
- Check that the webhook is still registered on the Git provider’s side — it can be removed if repository permissions changed or the app was disconnected and reconnected.
- Reconnect the Git provider integration if the connection itself looks stale.
- Confirm you’re pushing to the branch the site is actually configured to deploy from.
What you can’t change after the site exists
Site type, repository, domain and database can’t be edited on an existing site. If any of those needs to change, the fix is to delete the site and create it again with the right settings from the start — not to try to work around it in the current site.
What to send support
- The site domain and which app type it is (static, Node.js, Laravel, custom Docker).
- The exact error text from the deployment log.
- Which stage failed: clone, build, or start. The Failed step in the notice tells you this.
- Whether this ever worked before, and if so, what changed (branch, repository access, server).
Still stuck? Contact our support team for any of your queries.
For developers
To read the same failure details from a script or an AI agent, see read why a deploy failed in the Public API and MCP guide.
Frequently asked questions
Why did I get only one alert when my deploy failed several times?
xCloud tells you when a site starts failing or fails for a different reason, not on every repeat. Repeats of the same reason only add to the count in the notice on the Deployments page. No alert is sent when the site recovers: the notice goes away after the next successful deploy.
My deployment says ‘Permission denied (publickey)’. What do I do?
This is an access error, not a branch problem — changing the branch won’t help. Go to the site’s Git settings, configure the deploy key (or add the public key to the repository yourself as a read-only deploy key if xCloud can’t add it automatically), click Verify connection, then redeploy.
My build fails with ‘Is a directory’. What’s wrong?
Your .env file path points at a folder instead of a file. It’s joined to /var/www/
Can I change the repository or branch on an existing site after it’s created?
Site type, repository, domain and database can’t be changed on an existing site. If you need a different repository or a different site type, delete the site and create it again with the correct settings.
Why did my deployment start failing after I turned on ‘Stop the deployment when a command fails’?
A command in your deploy script was already failing, and the script used to carry on past it. Open the failed deployment to see the line and the command, then fix the command or add || true if it’s allowed to fail.
Can I let one command fail without stopping the deployment?
Yes. Add || true after that command, for example ./scripts/clear-cache.sh || true. The rest of the script still stops at any other failed command.