A rails 500 internal server error tells you almost nothing on screen, and that is frustrating. The fix starts in your application log: read the stack trace, raise the log level if needed, then step through the failing code with a debugger.
This page sits within the wider topic of ruby on rails debugging, which gathers related techniques in one place.
| Item | Value |
|---|---|
| Log level numbers | 0 (:debug) to 5 (:unknown) |
| Default level in the generated production config | :info |
| Default Rails log level | :debug |
| Log directory | Rails.root/log/ |
| Production log destination by default | STDOUT only |
These figures come from the Debugging Rails Applications guide and the edge version of the same guide. Defaults can change between Rails versions, so check the source before you rely on them.
Where do you look first when a request fails?
When a request fails, the browser page gives you little to work with, so the application log is the first place to check. The Rails guide explains that inspecting logs can show which database queries are made, which views are rendered, and how long different statements take to execute. That is exactly the context you need around a failure.
By default, each log is created under Rails.root/log/, and the file is named after the environment in which the application is running, according to the Rails guide. A failure in production will therefore not appear in your development log.
The edge guide adds a detail about destinations. In development and test environments, Rails writes to the file log/<environment>.log. In development it also writes to STDOUT, and in production it writes only to STDOUT by default, so on a hosted app you read wherever your platform collects that output.

A simple routine keeps you from chasing the wrong thing:
- Trigger the failing request once, so the log holds a fresh entry for it.
- Open the log or output stream for the environment where the error happened.
- Find the error message and the stack trace that follows it.
- Look for the first line that points into your own application code rather than a library.
The Rails guide lists how to analyze the stack trace among the skills it teaches, and the first application line is usually the best place to start reading.
Why is the error missing from the log?
Every message Rails logs carries a log level, and the level decides whether it is written. The guide states that a message is only written to the output if its level is equal to or higher than the configured log level. If your configured level is too high, lower-level detail never reaches the file.
The available levels and their integer values, from the edge guide, are:
- :debug is 0
- :info is 1
- :warn is 2
- :error is 3
- :fatal is 4
- :unknown is 5
The main guide says the default Rails log level is :debug, but that it is set to :info for the production environment in the default generated config/environments/production.rb. So a production app built from that template skips :debug messages unless you change it.
Defaults have differed between versions. The guide for Rails 7.0 says the default level is debug in all environments, so do not assume. You can ask your own app by calling Rails.logger.level, a method the guide names for exactly that purpose.
To change the level, the guide shows a config.log_level setting in config/environments/production.rb. It notes that a lower verbosity is useful when you want to log under development or staging without flooding your production log with unnecessary information. Treat any extra production verbosity as temporary and switch it back once you have your answer.
Add your own log lines around the failing code
When the stack trace points at a method but not at the bad value, add targeted log lines before and after the suspect code. The edge guide says you can access the Rails logger using Rails.logger, and its example wraps each message in a block, such as Rails.logger.debug followed by a block with the text to write.
You may be tempted to reach for puts instead. The guide points out that puts writes statements to STDOUT only and offers no way to switch statements on or off. In a production setting, it says, more control over logging is required.
The guide describes three ways to print, and they behave differently:
- puts writes to STDOUT only and calls to_s on what you pass it.
- p prints the raw object by calling inspect on it.
- pp pretty prints objects such as hashes and arrays in a more human-readable format.
Remember the level rule from the previous section. A line logged at :debug will not appear in a production setup that is configured for :info, so choose a level that your target environment will actually write.
Step through the failing code with a debugger
Logs show what happened, but a debugger lets you watch it happen. The guide explains that, using a debugger, you can step through the code line-by-line to ensure statements execute correctly and verify the application’s state.
The edge guide’s section on the debug gem covers these topics:
- Entering the debugger
- Debugger commands
- Programming your debugging workflow
- Remote debugging
Start the debugger just before the line your stack trace flagged, reproduce the request, and check each variable against what you expected. If the trace ends in a nil error, the walkthrough on undefined method for nil rails covers that case in more detail.
Check values in the view when an internal server error starts there
A failure can start in a template, where a log line is awkward to add. Rails provides three ways to inspect a variable directly in a view, as described in the main guide.
- debug returns a pre tag that renders the object using the YAML format.
- to_yaml converts any object to YAML, and you can pass the result into the simple_format helper.
- inspect is especially useful when working with arrays or hashes.
The edge guide also covers how to inject a Ruby console in your view, using the web-based console. Either way, remove temporary debug output from your views before you deploy.
Fix the cause, then plan for the next failure
Once the cause is fixed, you can decide what visitors should see if something else breaks later, and the guide to rails custom error pages is the place to start for that. Fixing the error and designing the error page are separate jobs, and it helps to keep them apart.
A short recap of the whole process:
- Reproduce the failure and read the log for the right environment.
- Confirm the log level lets the relevant messages through.
- Add Rails.logger lines where the trace is not enough.
- Use a debugger or a view helper to check the actual values.
- Remove temporary output and restore the normal log level.
Frequently asked questions
Where is the Rails log file?
Show answer
By default, each log is created under Rails.root/log/ and named after the environment, according to the Rails guide. The edge guide adds that production writes only to STDOUT by default, so check your hosting setup too.
Why does my production log have no debug messages?
Show answer
The generated production config sets the level to :info, so :debug messages are not written, as the main guide describes. Check your own value with Rails.logger.level.
What are the Rails log levels?
Show answer
They are :debug, :info, :warn, :error, :fatal and :unknown, numbered 0 up to 5, per the Rails guide.
Should I use puts or Rails.logger to debug?
Show answer
Prefer Rails.logger. The edge guide notes that puts writes to STDOUT only and gives no way to enable or disable individual statements.



