Troubleshoot your deployment
This section gives you some ideas of how to start troubleshooting if your deployment doesn’t work as expected. If you’re still stuck after reading, then visit our community forum for more help.
Try this first
If the error you get isn’t obvious or specific, then try these basic steps first, to either fix the problem or to arm yourself with knowledge.
Update flyctl
By default, flyctl (the Fly CLI), updates automatically.
But if you’ve disabled automatic updates, then you should update flyctl:
fly version update
We frequently add new features to flyctl, so you should keep it up to date to avoid breaking things. You can also turn automatic updates back on with:
fly settings autoupdate enable
Check connectivity with fly doctor
Run some basic connectivity test for things like WireGuard, IP addresses, and local Docker instance:
fly doctor
Any failures in the fly doctor
output point to where you can start troubleshooting.
Review your fly.toml
configuration
Double-check the formatting and configuration options in your fly.toml
file. Besides checking port numbers, you should also review any recent changes and make sure you’re following the conventions described in the app configuration docs.
Get more information about failures
Logs have knowledge.
Check the logs
Check the logs of the app when it’s running or when you run fly deploy
. Run your command in one terminal window and open a second window to view the logs.
To get the most recent log entries:
fly logs
Look for error messages that indicate why the app or deploy is failing, and the logs that occurred just before the app crashed or the deploy failed.
If you can see messages about the app just exiting, then there’s likely an issue with your project source, and you’ll need to address that before you can deploy successfully.
Activate debug logging
Activate debug level logs on a command, like fly deploy
:
LOG_LEVEL=debug fly <command>
LOG_LEVEL=debug prints all the logs into the console as the command runs.
Inspect with SSH
You can use fly ssh console
to get a shell on a running Machine in your app. Use fly ssh console -s
to select a specific Machine.
WARNING The app is not listening on the expected address (Host and port checking)
Check your app’s host and port settings. To be reachable by Fly Proxy, an app needs to listen on 0.0.0.0
and bind to the internal_port
defined in the fly.toml
configuration file.
If your app is not listening on the expected address and the configured port, you’ll get the following warning message when you deploy your app:
WARNING The app is not listening on the expected address and will not be reachable by fly-proxy.
The message supplies:
- The host address your app should be listening on, which is
0.0.0.0:<internal_port value>
. - A list of processes inside the Machine with TCP sockets in LISTEN state. This includes
/app
, which might show something like[ :: ]:8080
; the host address your app is trying to listen on. (You can ignore hallpass on port 22, which is used for SSH on Machines.)
Fix the “app is not listening on the expected address” error
When you launch a new Fly App, the value of internal_port
in the fly.toml
file depends on the default port for your framework or the EXPOSE
instruction in your Dockerfile. The default port when the fly launch
command doesn’t detect a framework or find ports set in a Dockerfile is 8080
.
To fix the error, you can either:
- Configure your app to listen on host
0.0.0.0:<internal port value in fly.toml>
, or - Configure your app to listen on host
0.0.0.0:<framework default or other port>
and change theinternal_port
value in thefly.toml
configuration file to match.
For example, if your app listens on 0.0.0.0:3000
, then set internal_port = 3000
in the fly.toml
.
Why does my app listen on localhost with a different port number?
A lot of frameworks will listen on localhost
/127.0.0.1
by default so that the developer can connect to the app. Different frameworks also define different default ports, like 3000, 8000, or 8080, for example. It can be easy to make a mistake and configure your app in a way that makes it impossible for the Fly Proxy to route requests to it. And it can be difficult to debug, especially if your framework doesn’t print the listening address to logs and your image doesn’t have netstat
or ss
tools.
Learn more about connecting to an app service.
Example - Configure port and host in a Fastify Node app
How do you figure out which address port your app is listening on? Check your code for where the web service started up - sometimes it’ll be just serve()
orlisten()
and what’s missing is parameters for the address and/or port.
For example, here’s a getting-started app for Fastify (Node.js):
// Require the framework and instantiate it
// ESM
import Fastify from 'fastify'
const fastify = Fastify({
logger: true
})
// CommonJs
const fastify = require('fastify')({
logger: true
})
// Declare a route
fastify.get('/', function (request, reply) {
reply.send({ hello: 'world' })
})
// Run the server!
fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Server is now listening on ${address}
})
This example will work locally, but when you run fly deploy
you’ll get the “app is not listening on the expected address” warning.
You can modify the example to listen on host 0.0.0.0
and to print a log with the listening address:
...
fastify.listen({ port: 3000, host: '0.0.0.0' }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
})
Then make sure that the internal_port
value in fly.toml
is set to 3000
.
Smoke checks failing
Smoke checks run during deployment to make sure that a crashing app doesn’t get successfully deployed to all your app’s Machines. If possible, the smoke check failure output includes an excerpt of the logs to help you diagnose the issue with your app. Common issues with new apps might include Machine size, missing environment variables, or other problems with the app’s configuration.
Health checks failing
We don’t automatically add health checks to your fly.toml
file when you create your app. The health checks that you subsequently add to your app can fail for a number of reasons.
A good first step can be to look at a failed Machine and see what you can figure out. To see the specific Machine status, run fly status --all
to get a list of Machines in your app. Then run fly machine status <machine id>
. This will give you a lot more information. Make sure you check the exit code: if it’s non-zero, then your process crashed.
Out-of-memory (OOM) or high CPU usage
If your Machine’s resources are reaching their limits, then this could slow everything down, including accepting connections and responding to HTTP requests. Slow responses can trigger health check failures.
You might see out-of-memory errors in logs. Some apps (like Node.js apps that use Prisma) can be RAM-intensive. So your app may be killed for out-of-memory (OOM) reasons. The solution is to just add more RAM.
If you see high CPU usage in metrics you might need to select a new preset CPU/RAM combination, or even update only the CPU on an individual Machine.
Grace period
Grace period is the time to wait after a Machine starts up before checking its health.
If your app takes a longer time to start up, then set a longer health check grace period.
To increase the grace period for your app, update the fly.toml
file. For example, if your app takes 4 seconds to start up, then you could set the grace period to 6 seconds:
# If you're using tcp_checks
[[services.tcp_checks]]
grace_period = "6s"
...
# If you're using http_checks
[[services.http_checks]]
grace_period = "6s"
...
# or
[[http_service.checks]]
grace_period = "6s"
...
More issues that cause health checks to fail
- Something is blocking your
accept
loop. This would prevent the health check from connecting. - You’re using an HTTP check and the response is not a 200 OK.
- Your app is not catching all thrown errors. If your app panics before it can respond to an HTTP request, it will look like a broken request to the health checker.
Other common deployment issues
A miscellaneous list of potential pitfalls.
HTTPS in fly.toml
If you specify in your fly.toml
that protocol = "https"
, this means that your application must be serving TLS directly. If you have enabled https, try disabling it for debugging.
Missing variables
For example, if you notice in your logs that the database is failing to connect to DATABASE_URL
, make sure that variable is set.
To see your app’s secrets and environment variables, run:
fly config env
Buildpack-based deploys
First of all, we think using a Dockerfile rather than buildpacks is more reliable and faster to deploy. If possible, making the switch is probably a good idea!
That’s because buildpacks come with lots of dependencies to build different stacks rather than just what you need. On top of that, we’ve seen buildpack providers upgrade the image on Docker Hub and things Stop Working (even with no code changes on your app). Running fly launch
already generates Dockerfiles for many popular frameworks.
That said, if the build used to work, then you can try using a previous, fixed buildpack version so it’s back in a known good state.