Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →To debug a crashing Elixir GenServer, identify the server’s termination reason and stack trace, map the last request or message to the callback that handled it, then check that callback’s patterns and return value. Also distinguish a server crash from a caller timeout or an exit propagated through a link. A supervisor may restart the process, but that does not fix the cause and can reset its in-memory state.
Start with the termination evidence
Capture the error log and exception or exit reason before changing restart settings. Record the GenServer PID or registered name, the time of the failure, the relevant stack trace, and the request or message being processed. The top application frame in the stack trace often points to the callback work that failed; use it alongside the triggering input rather than treating the final error line as the whole explanation.
Separate the server’s exit from a caller’s GenServer.call/3 exit. The call timeout limits how long the caller waits for a reply. If no reply arrives in that period, the caller exits; a reply arriving later can still be placed in the caller’s mailbox. A timeout by itself therefore does not prove that the server crashed. See the GenServer API reference.
Find which callback handled the event
Match the actual incoming message to its callback. In the client-server model, synchronous requests are handled by handle_call/3, asynchronous requests by handle_cast/2, and other messages—including ordinary messages sent with send/2 and monitor :DOWN notifications—by handle_info/2. A message with no matching clause, or no suitable callback, can expose a crash. The Elixir client-server guide explains these callback roles.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errors#1 Best Overall
- For a call, inspect the exact request term passed to
GenServer.call/3. - For a cast, inspect the term passed to
GenServer.cast/2and remember that a cast does not guarantee the server received the message. - For an info message, check timers, raw messages, monitor notifications, and any other messages not sent through call or cast.
Compare the logged message with every relevant pattern match. If a request can be invalid but the server can safely continue, validate it deliberately and return an informative error from a call. If it violates an invariant such that continuing would leave the process in an unsafe state, stopping may be the correct choice instead of adding a broad fallback that hides the defect.
Check callback return values and exceptions
Review each branch of the identified callback against that callback’s documented return contract. A supported return has the required tuple shape and a valid next state; an invalid return can terminate the server. The GenServer API reference lists the accepted forms for each callback.
An exception, explicit exit, or {:stop, ...} return can also end a server. Inspect the application frame where the failure originates and trace the request and state that led to it. Rescue only errors that are expected and recoverable; broad rescue can obscure a bug or allow a process to continue with broken state.
Startup failures are a separate case: init/1 has its own return contract. If it fails, the process may never start successfully, so investigate initialization rather than looking for a later message-handling callback.
Rank #3
Inspect a live or recurring server
If the process is still alive or the problem recurs intermittently, Elixir’s :sys facilities can reveal its state and recent activity. The GenServer debugging guidance in the GenServer API reference describes these options:
:sys.get_state/2retrieves callback state.:sys.get_status/2retrieves status details.:systracing can show system events such as received messages, sent replies, and state changes.
Use state inspection and tracing selectively. State or messages may contain secrets, and tracing a busy process can produce large volumes of sensitive or noisy output.
Check linked exits and shutdowns
A GenServer started with start_link/3 is linked to its parent. The server may have failed in its own callback, received an exit from a linked process or parent, or been stopped as part of a supervision-tree shutdown. Check the recorded exit reason and the surrounding supervisor and process logs to distinguish these paths.
Shutdown behavior also affects cleanup. A supervisor’s shutdown timeout and :brutal_kill setting affect whether terminate/2 has a chance to run. The API reference warns that terminate/2 is not guaranteed to be called for every exit, so do not rely on it as the only way to preserve essential data or release resources.
Best Value
Understand the restart before changing it
Supervisors restart children according to their child specifications and strategy. A restart can restore availability while discarding volatile process state: the Supervisor documentation’s counter example crashes on invalid input and starts again with its initial value. Check both the child’s restart policy and the supervisor strategy, such as :one_for_one or :one_for_all, in light of whether sibling processes depend on each other. The Supervisor API reference explains restart behavior and exit reasons.
Confirm whether an exit is normal, a shutdown, or abnormal before assuming the child should restart. Restart policies can be permanent, transient, or temporary; in general, they determine whether a child restarts for every exit, only abnormal exits, or not at all. Repeated failures may also reach the supervisor’s restart intensity and cause the supervisor itself to stop. Correlate the original crash reason with supervisor logs rather than changing policy just to silence a crash report.
Choose a fix that matches the failure
- Unexpected request or message: validate the actual term and add explicit handling for supported inputs. For calls, return an error response when safe; stop if the process cannot preserve its invariants.
- Missing info handling: add an intentional
handle_info/2path for supported timers, raw messages, or monitor notifications, and decide how truly unexpected messages should be handled. - Invalid return or callback exception: correct the callback branch and its state transition. Do not hide an invariant failure with a catch-all rescue.
- Linked process or shutdown exit: identify the process and exit reason that propagated, then adjust lifecycle or shutdown behavior only if it matches the intended design.
- Restart loop: fix the original repeatable failure and verify the restart policy and strategy against state reconstruction and sibling dependencies.
Choose between call and cast based on the operation’s semantics. The guide says synchronous calls are generally the default because waiting for a reply provides back-pressure; casts are asynchronous and do not confirm receipt. Do not switch to a cast merely to avoid a call failure if the caller needs a result or the operation needs that back-pressure.
Verify the repair
- Reproduce the triggering request or message with the corrected handling in place.
- Confirm the callback returns a documented result and that the server responds or updates state as intended.
- Check supervisor logs and restart history to confirm the process is no longer repeatedly restarting.
- If recovery depends on state, verify that the state can be reconstructed after restart or preserved through an appropriate durable mechanism.
Elixir’s API describes a GenServer as “a process like any other Elixir process” that can keep state and execute code asynchronously. Treat its crash as a process-lifecycle problem as well as a callback bug: the useful fix addresses the initiating failure and confirms that the surrounding supervision behavior is appropriate. The quotation is from the GenServer API reference.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




