Using Logs to Troubleshoot Job Errors

Earn 25 points (50 with Pro) in two steps

  1. ① Read through the lesson — each section gets a ✓ as you scroll through it.
  2. ② When every section has a ✓, tap Complete lesson.

0 of 9 read · keep scrolling

✦ See fewer ads and earn double points — 50 a lesson instead of 25 — with Pro

Lesson: Using Logs to Troubleshoot Model Training Job Errors

Introduction: The Critical Role of Logging in Machine Learning

In the lifecycle of machine learning development, the vast majority of your time is spent not in designing complex architectures, but in debugging failed training jobs. When you submit a training script to a remote cluster, a cloud provider, or even a local container, you are handing off control to an environment you cannot directly observe. If the job fails silently or crashes mid-epoch, you are left with a "black box" scenario. This is where logging becomes your most essential tool.

Logging is the systematic recording of events, errors, performance metrics, and state transitions during the execution of your code. Unlike standard print statements, which are often lost in the buffer or difficult to filter, structured logging allows you to reconstruct the history of a training job. It provides the breadcrumbs necessary to identify whether a failure was caused by a hardware bottleneck, a data pipeline corruption, an incompatible library version, or an exploding gradient. Understanding how to interpret these logs is the difference between a productive engineering workflow and hours of frustrating guesswork.

This lesson explores the strategies for implementing robust logging, interpreting common error patterns, and establishing a workflow for troubleshooting machine learning training jobs. We will look beyond basic debugging and move into the realm of observability, ensuring that your training infrastructure provides actionable insights whenever a job deviates from its expected path.


Not read yet

The Anatomy of Training Logs

To effectively troubleshoot, you must first understand what constitutes a useful log. A training log is more than just a stream of text; it is a time-series record of the internal state of your model. When a job fails, the logs are the primary diagnostic artifact you have.

Standard Output (stdout) vs. Standard Error (stderr)

Most training environments separate output into two streams. stdout is typically used for progress bars, epoch-level metrics, and informational messages. stderr is reserved for warnings and errors. A common mistake is to ignore stderr because the job "seems" to be running, or to have stdout cluttered with debugging information that hides the actual errors.

Structured Logging

Modern machine learning workflows benefit from structured logging, where messages are formatted as JSON or key-value pairs. Instead of logging a plain string like "Loss is 0.5", a structured logger produces: {"timestamp": "2023-10-27T10:00:00Z", "level": "INFO", "epoch": 5, "loss": 0.5, "event": "training_step"}. This format is machine-readable, allowing you to use external tools to query logs, build dashboards, and set up alerts for specific error thresholds.

Callout: Logging vs. Monitoring While both are essential, they serve different purposes. Logging provides a granular, event-based history of what happened inside the code, which is vital for post-mortem debugging. Monitoring provides a high-level view of system health, such as GPU temperature or CPU utilization over time, which is better for detecting long-term trends or infrastructure bottlenecks.


Not read yet

Setting Up Effective Logging in Python

Python’s built-in logging module is the industry standard for production-grade scripts. Avoid using print() statements for anything other than quick, temporary local testing. The logging module offers levels of severity (DEBUG, INFO, WARNING, ERROR, CRITICAL), which allow you to filter the noise.

Implementing a Basic Logging Configuration

Below is a template for setting up a logger that outputs to both the console and a file. This is useful because it allows you to see progress in real-time while maintaining a persistent record for after-the-fact analysis.

import logging
import sys

def setup_logger(log_file='training.log'):
    logger = logging.getLogger('training_logger')
    logger.setLevel(logging.DEBUG)
    
    # Create file handler
    file_handler = logging.FileHandler(log_file)
    file_handler.setLevel(logging.DEBUG)
    
    # Create console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setLevel(logging.INFO)
    
    # Create formatter and add to handlers
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    file_handler.setFormatter(formatter)
    console_handler.setFormatter(formatter)
    
    # Add handlers to the logger
    logger.addHandler(file_handler)
    logger.addHandler(console_handler)
    
    return logger

# Usage in a training script
logger = setup_logger()
logger.info("Starting training job...")
try:
    # Training logic here
    pass
except Exception as e:
    logger.error(f"Training failed with error: {e}", exc_info=True)

Note: The exc_info=True argument in the logger is crucial. It tells the logger to capture the full stack trace of the exception. Without this, you only get the error message, which is often insufficient for debugging complex deep learning models.


Not read yet

Common Error Patterns and How to Interpret Them

When you encounter an error during training, the stack trace is your map. However, stack traces can be intimidating. Learning to identify the "source of truth" in a trace is a critical skill.

1. The Out-of-Memory (OOM) Error

OOM errors are the most common issue in deep learning. They often manifest as a RuntimeError: CUDA out of memory.

  • How to spot it: The log will show a sudden termination of the training loop, typically right after a loss.backward() call.
  • Troubleshooting: Check the logs for the exact moment the memory usage spiked. You may need to reduce the batch size, use gradient accumulation, or enable mixed-precision training.
  • Prevention: Log your GPU memory usage periodically. Many libraries like PyTorch allow you to print torch.cuda.memory_summary() at the end of each epoch to track memory growth.

2. The Exploding/Vanishing Gradient Error

This error often doesn't crash the script immediately but causes the loss to become NaN (Not a Number).

  • How to spot it: The training logs will show the loss value transitioning from a valid number to NaN or inf.
  • Troubleshooting: Check your learning rate. If it is too high, the gradients may grow uncontrollably. Consider implementing gradient clipping.
  • Log Strategy: Include a check in your training loop that logs an alert if loss is NaN.

3. Data Pipeline Stalls

Sometimes, a training job hangs indefinitely. The logs show the model is "running," but no progress is made.

  • How to spot it: The timestamps in your logs will stop updating, or you will see a large gap between log entries.
  • Troubleshooting: This is usually a deadlock in the data loader. It often happens when using multiple workers (num_workers > 0) in a PyTorch DataLoader. Try setting num_workers=0 as a test; if the problem disappears, you have a multi-processing issue.

Not read yet

Best Practices for Logging Training Jobs

To make your logs useful, you must establish consistent habits. A disorganized set of log files is almost as bad as having no logs at all.

1. Log Hyperparameters at the Start

Always log the configuration of your job (batch size, learning rate, optimizer, model architecture) before the training loop starts. If you look at a log file six months later, you need to know exactly what parameters were used to produce those results.

2. Use Unique Run Identifiers

If you are running multiple experiments, ensure each one creates a unique log file. Use a timestamp or a unique job ID in the filename. This prevents overwriting logs from previous runs and makes it easy to compare results.

3. Log Hardware Utilization

Include periodic logs of system metrics such as GPU utilization, CPU load, and disk I/O. If a job is slow, these logs will tell you if the bottleneck is the GPU (compute-bound) or the data loader (I/O-bound).

4. Implement Health Checks

At the start of your script, log the versions of your core libraries (torch, tensorflow, numpy, cuda). Version mismatches are a frequent cause of "ghost" bugs that appear only on specific training nodes.

Tip: Use a centralized logging service if you are working in a team or a distributed environment. While writing to local files is fine for simple scripts, services like Weights & Biases, MLflow, or cloud-native tools (like AWS CloudWatch or Google Cloud Logging) allow you to aggregate logs from multiple nodes into a single, searchable interface.


Not read yet

Step-by-Step: Debugging a Failed Job

When you receive a notification that a training job has failed, follow this systematic approach to isolate the cause:

  1. Check the Job Status: Confirm if the process exited with a non-zero exit code. A code like 137 usually indicates an Out-of-Memory (OOM) kill by the operating system, whereas other codes might point to a Python exception.
  2. Scan the Tail of the Log: Always look at the last 50 lines of the log file first. The most recent log entries contain the exception that caused the crash.
  3. Search for "Exception" or "Error": Use a text search tool (like grep or the search function in your text editor) to look for these keywords throughout the entire log file to ensure you haven't missed earlier warnings that led to the final crash.
  4. Review the Stack Trace: Identify the line of code that triggered the error. Is it in your training script, or is it in a library (like torch or pandas)? If it is in a library, check if you are passing the expected inputs (e.g., shapes of tensors).
  5. Replicate Locally: Attempt to reproduce the error on a smaller scale. If the job fails after 100 epochs on a cluster, try running it for 5 epochs on your local machine with a subset of the data.
  6. Verify Environment Parity: Compare the log of the failed job with a known successful job. Look for differences in library versions, file paths, or environment variables.

Not read yet

Comparison of Logging Approaches

Depending on the complexity of your project, you might choose different strategies for managing your logs.

Approach Best For Pros Cons
Standard Print Rapid prototyping Extremely easy to implement No persistence, hard to filter, lost in production
Python Logging Standard scripts Flexible, configurable, standard library Requires setup, can be verbose
Experiment Tracking Research/Production Automatic logging, visualization, searchable Requires external dependencies
System/Cloud Logs Distributed training Centralized, persistent, searchable Can incur costs, requires configuration

Common Pitfalls and How to Avoid Them

Even experienced engineers fall into common traps when setting up logging. Avoiding these will save you significant time during the training phase.

Pitfall 1: Buffering Issues

By default, Python may buffer your log output. If your program crashes, the buffered logs might not be written to the disk, meaning you lose the final (and most important) lines of output.

  • The Fix: Always set your log handlers to flush immediately or disable buffering, especially in distributed environments where output streams are often redirected.

Pitfall 2: Over-Logging

Logging every single training step in a high-frequency loop can create gigabytes of text files, which slows down the training process and makes the log files impossible to parse.

  • The Fix: Log progress at defined intervals (e.g., every 100 steps or once per epoch). Reserve detailed logging for debugging sessions only.

Pitfall 3: Ignoring Warnings

Warnings (e.g., "UserWarning: TypedStorage is deprecated") are often ignored because they don't break the code. However, they can signal that your code is relying on outdated patterns that may break in future library versions.

  • The Fix: Treat warnings as "soft errors." Periodically review them and address them to keep your codebase clean and future-proof.

Pitfall 4: Hardcoding Paths

Hardcoding log paths like /home/user/logs/ will cause your code to fail when run on a different machine or in a containerized environment.

  • The Fix: Use relative paths or environment variables to define where logs should be stored. Ensure your script checks if the directory exists and creates it if necessary.

Warning: Never log sensitive information. This includes API keys, database credentials, or private user data. If you are using a cloud-based logging service, this information will be stored in plain text and could be accessed by others. Always use environment variables or secret management tools for sensitive configuration.


Not read yet

Advanced Troubleshooting: Analyzing Distributed Training Logs

When you move to multi-GPU or multi-node training, logging becomes exponentially more complex. You are no longer dealing with one log file, but potentially dozens.

The "Stuck Worker" Problem

In distributed training, one node might fail while others continue to run. If you are only looking at the "primary" node's logs, you might not see the error occurring on a worker node.

  • Strategy: Implement a logging strategy that aggregates logs from all ranks. Most distributed frameworks (like torch.distributed) provide utilities to identify which rank is producing which log entry. Always prefix your log lines with the Rank ID, for example: [Rank 0] INFO: Epoch 1 starting....

Network Timeouts

Distributed training relies on nodes communicating with each other. A network glitch can cause a timeout that is difficult to diagnose.

  • Strategy: Look for socket errors or connection resets in your logs. If you see these, the issue is likely infrastructure-related (e.g., firewall, network congestion) rather than a bug in your model code.

Not read yet

Summary of Best Practices for Production

  1. Standardize: Use the logging module consistently across all your training projects.
  2. Contextualize: Always include timestamps, log levels, and contextual information (e.g., epoch, batch index, worker ID).
  3. Persist: Ensure logs are written to a persistent location, not just the temporary directory of the training container.
  4. Monitor: Use tools that can trigger alerts if error rates spike or if a job stops sending heartbeats.
  5. Review: Periodically audit your logs to identify and resolve recurring warnings or inefficient patterns.
  6. Clean: Implement a log rotation strategy so that your disk doesn't fill up with old, unused log files.

Key Takeaways

  • Logs are your primary diagnostic tool: Treat them as first-class citizens in your development process. A training job without logging is a job you cannot debug.
  • Use the logging module: Move away from print() statements immediately. The logging module provides the structure and severity levels needed for professional-grade debugging.
  • Capture the stack trace: Always configure your logger to capture exc_info when an exception occurs. Knowing where the crash happened is 90% of the battle.
  • Identify the failure pattern: Learn to recognize common issues like OOM errors, NaN losses, and data pipeline stalls by the patterns they leave in your log files.
  • Aggregated logging is essential for scale: As you move to multi-GPU or distributed training, ensure your logs are properly tagged with rank IDs and aggregated into a central location.
  • Proactive maintenance: Address warnings and "soft errors" before they become critical failures. Keep your environment and library versions consistent across all training runs.
  • Security first: Never log sensitive information. Ensure your logging configuration handles secrets safely and complies with your organization's data privacy policies.

By mastering the art of logging, you transition from simply "running code" to "managing experiments." This maturity allows you to iterate faster, maintain more complex models, and ultimately build more reliable machine learning systems. When a job fails—and it will—you will have the confidence to open the logs, find the culprit, and get back to training in minutes rather than hours.

Not read yet

Each section gets a ✓ as you scroll through it. Tap the button to jump to the next one.