Skip to main content
RapidDev - Software Development Agency
replit-tutorial

How to trace runtime errors in Replit

When your Python script crashes in Replit, the Console shows a traceback — a stack of error messages that tells you exactly which file, line number, and function caused the failure. This tutorial teaches you to read tracebacks from bottom to top, use the logging module for structured error tracking, and add try/except blocks to handle errors gracefully instead of crashing.

What you'll learn

  • Read Python tracebacks from bottom to top to identify the exact error location
  • Recognize and fix the five most common Python runtime errors
  • Use the logging module instead of print statements for structured debugging
  • Add try/except blocks to handle errors gracefully in production
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner10 min read15-20 minutesAll Replit plans (Starter, Core, Pro). Python 3.x required. Works with any Python project.March 2026RapidDev Engineering Team
TL;DR

When your Python script crashes in Replit, the Console shows a traceback — a stack of error messages that tells you exactly which file, line number, and function caused the failure. This tutorial teaches you to read tracebacks from bottom to top, use the logging module for structured error tracking, and add try/except blocks to handle errors gracefully instead of crashing.

Read Python Tracebacks and Debug Runtime Errors in Replit

This tutorial teaches you how to find and fix Python runtime errors using Replit's Console output and Shell. You will learn to read Python tracebacks, understand the most common error types (NameError, TypeError, KeyError, AttributeError), use the logging module for structured error tracking, and add error handling to prevent crashes. Every debugging technique works entirely within the browser — no external tools or terminal setup required.

Prerequisites

  • A Replit account (free Starter plan works)
  • A Python Repl with code that produces runtime errors
  • Basic Python knowledge (variables, functions, imports)
  • Familiarity with the Replit Console and Shell tabs

Step-by-step guide

1

Read the traceback from bottom to top

When your Python script crashes, the Console shows a traceback — a multi-line error message. Most beginners read it top to bottom, but the most important information is at the bottom. The last line tells you the error type and message (e.g., NameError: name 'x' is not defined). The line just above it shows the exact code that caused the error. Lines above that show the call chain — which function called which. Start at the bottom and work your way up to understand how your code reached the failing point.

typescript
1# This code will produce a traceback:
2def calculate_total(items):
3 total = 0
4 for item in items:
5 total += item['price'] * item['quantity']
6 return total
7
8orders = [
9 {'price': 10, 'quantity': 2},
10 {'price': 25}, # Missing 'quantity' key!
11]
12
13result = calculate_total(orders)
14
15# Traceback output:
16# Traceback (most recent call last):
17# File "main.py", line 12, in <module>
18# result = calculate_total(orders)
19# File "main.py", line 4, in calculate_total
20# total += item['price'] * item['quantity']
21# KeyError: 'quantity'

Expected result: You can identify the error type (KeyError), the line number (line 4), the function (calculate_total), and the missing data ('quantity' key) from the traceback.

2

Identify the five most common Python runtime errors

Most Python crashes in Replit fall into five categories. NameError means you used a variable that does not exist — usually a typo. TypeError means you passed the wrong data type to a function (like adding a string to a number). KeyError means a dictionary key does not exist. AttributeError means you called a method on an object that does not have it. IndexError means you tried to access a list index that is out of range. Recognizing these error types immediately tells you where to look in your code.

typescript
1# NameError typo in variable name:
2user_name = "Alice"
3print(username) # NameError: name 'username' is not defined
4
5# TypeError wrong data type:
6age = "25"
7result = age + 10 # TypeError: can only concatenate str to str
8
9# KeyError missing dictionary key:
10user = {'name': 'Alice'}
11print(user['email']) # KeyError: 'email'
12
13# AttributeError wrong method on wrong type:
14my_list = [1, 2, 3]
15my_list.split(',') # AttributeError: 'list' has no attribute 'split'
16
17# IndexError list index out of range:
18items = ['a', 'b', 'c']
19print(items[5]) # IndexError: list index out of range

Expected result: You can recognize these five error types by name and know what to look for in your code when each one appears in the Console.

3

Add logging instead of print statements

While print() works for quick debugging, the logging module provides timestamps, severity levels, and structured output that make it much easier to trace issues in larger programs. Set up logging at the top of your script with basicConfig, then use logging.info() for normal messages, logging.warning() for potential issues, and logging.error() for failures. Log output appears in the Console alongside your regular output but with timestamps and levels that help you reconstruct what happened when something goes wrong.

typescript
1import logging
2
3# Set up logging with timestamps and severity levels
4logging.basicConfig(
5 level=logging.DEBUG,
6 format='%(asctime)s [%(levelname)s] %(message)s',
7 datefmt='%H:%M:%S'
8)
9
10def fetch_user(user_id):
11 logging.info(f"Fetching user {user_id}")
12
13 if not isinstance(user_id, int):
14 logging.error(f"Invalid user_id type: {type(user_id).__name__}")
15 return None
16
17 # Simulate database lookup
18 users = {1: 'Alice', 2: 'Bob'}
19 user = users.get(user_id)
20
21 if user is None:
22 logging.warning(f"User {user_id} not found")
23 else:
24 logging.info(f"Found user: {user}")
25
26 return user
27
28fetch_user(1) # INFO: Found user: Alice
29fetch_user(99) # WARNING: User 99 not found
30fetch_user('x') # ERROR: Invalid user_id type: str

Expected result: The Console shows timestamped log entries with severity levels like [INFO], [WARNING], and [ERROR] instead of plain print output.

4

Wrap risky code in try/except blocks

Instead of letting your script crash when an error occurs, wrap risky operations in try/except blocks to catch errors and handle them gracefully. This is especially important for code that makes API calls, reads files, or processes user input. Catch specific exception types rather than using bare except — this prevents masking unexpected bugs. Log the error details with logging.exception() which includes the full traceback in the log output.

typescript
1import logging
2import json
3
4logging.basicConfig(
5 level=logging.DEBUG,
6 format='%(asctime)s [%(levelname)s] %(message)s'
7)
8
9def process_api_response(raw_data):
10 try:
11 data = json.loads(raw_data)
12 user_name = data['user']['name']
13 logging.info(f"Processed user: {user_name}")
14 return user_name
15 except json.JSONDecodeError as e:
16 logging.error(f"Invalid JSON response: {e}")
17 return None
18 except KeyError as e:
19 logging.error(f"Missing key in response: {e}")
20 return None
21 except Exception as e:
22 logging.exception(f"Unexpected error processing response")
23 return None
24
25# Test with valid data:
26process_api_response('{"user": {"name": "Alice"}}')
27
28# Test with invalid JSON:
29process_api_response('not json')
30
31# Test with missing key:
32process_api_response('{"user": {}}')

Expected result: The script handles all three error cases without crashing. Each error is logged with a descriptive message, and the function returns None instead of raising an exception.

5

Use sys.exc_info() for detailed error inspection

For complex debugging scenarios, Python's sys.exc_info() function gives you detailed information about the current exception including the exception type, value, and full traceback object. This is useful when you need to inspect or forward error details programmatically, such as sending error reports to an external service or creating custom error pages. Use it inside an except block to capture the active exception.

typescript
1import sys
2import traceback
3import logging
4
5logging.basicConfig(level=logging.DEBUG, format='%(asctime)s [%(levelname)s] %(message)s')
6
7def risky_operation():
8 data = {'a': 1}
9 return data['b'] # Will raise KeyError
10
11try:
12 risky_operation()
13except Exception:
14 exc_type, exc_value, exc_tb = sys.exc_info()
15
16 logging.error(f"Exception type: {exc_type.__name__}")
17 logging.error(f"Exception message: {exc_value}")
18
19 # Get the full traceback as a string
20 tb_lines = traceback.format_exception(exc_type, exc_value, exc_tb)
21 full_traceback = ''.join(tb_lines)
22 logging.error(f"Full traceback:\n{full_traceback}")
23
24 # Extract the specific file and line number
25 tb_details = traceback.extract_tb(exc_tb)
26 for filename, line, func, text in tb_details:
27 logging.error(f" File: {filename}, Line: {line}, Function: {func}")
28 logging.error(f" Code: {text}")

Expected result: The Console shows the exception type, message, full traceback, and individual file/line/function details for each frame in the call stack.

Complete working example

debug_example.py
1# debug_example.py Complete Python debugging template for Replit
2import os
3import sys
4import logging
5import traceback
6
7# Configure logging with timestamps and severity levels
8logging.basicConfig(
9 level=logging.DEBUG,
10 format='%(asctime)s [%(levelname)s] %(funcName)s: %(message)s',
11 datefmt='%Y-%m-%d %H:%M:%S'
12)
13
14logger = logging.getLogger(__name__)
15
16
17def safe_get_env(key, default=None):
18 """Safely get an environment variable with logging."""
19 value = os.getenv(key, default)
20 if value is None:
21 logger.warning(f"Environment variable '{key}' not set")
22 else:
23 logger.debug(f"Loaded env var: {key}")
24 return value
25
26
27def process_data(records):
28 """Process a list of records with error handling."""
29 logger.info(f"Processing {len(records)} records")
30 results = []
31
32 for i, record in enumerate(records):
33 try:
34 name = record['name']
35 score = int(record['score'])
36 grade = 'Pass' if score >= 60 else 'Fail'
37 results.append({'name': name, 'score': score, 'grade': grade})
38 logger.debug(f"Record {i}: {name} = {grade}")
39
40 except KeyError as e:
41 logger.error(f"Record {i} missing required key: {e}")
42 logger.error(f"Record contents: {record}")
43
44 except (ValueError, TypeError) as e:
45 logger.error(f"Record {i} has invalid score value: {e}")
46
47 except Exception:
48 logger.exception(f"Unexpected error processing record {i}")
49
50 logger.info(f"Successfully processed {len(results)}/{len(records)} records")
51 return results
52
53
54def main():
55 logger.info("Application started")
56 logger.info(f"Python version: {sys.version}")
57
58 # Load configuration from environment
59 api_key = safe_get_env('API_KEY')
60 debug_mode = safe_get_env('DEBUG', 'false') == 'true'
61
62 # Sample data some records have deliberate errors
63 test_data = [
64 {'name': 'Alice', 'score': '95'},
65 {'name': 'Bob', 'score': '72'},
66 {'name': 'Charlie'}, # Missing 'score'
67 {'name': 'Diana', 'score': 'N/A'}, # Invalid score
68 {'name': 'Eve', 'score': '88'},
69 ]
70
71 results = process_data(test_data)
72
73 print("\n=== Results ===")
74 for r in results:
75 print(f" {r['name']}: {r['score']} ({r['grade']})")
76
77 logger.info("Application finished")
78
79
80if __name__ == '__main__':
81 main()

Common mistakes when tracing runtime errors in Replit

Why it's a problem: Reading tracebacks from top to bottom and getting lost in the call chain

How to avoid: Always start at the bottom line. The last line shows the error type and message. Work upward to find the file, line number, and function that caused it.

Why it's a problem: Using bare except: blocks that catch everything including KeyboardInterrupt

How to avoid: Always specify the exception type: except KeyError as e: or except (ValueError, TypeError) as e:. Use except Exception as a last resort.

Why it's a problem: Using only print() for debugging and losing track of output in large programs

How to avoid: Switch to the logging module with timestamps and severity levels. It makes it much easier to find errors in output that may span hundreds of lines.

Why it's a problem: Catching exceptions silently without logging or re-raising them

How to avoid: Always log the error details inside except blocks. Silent exception handling hides bugs and makes them impossible to diagnose later.

Best practices

  • Read tracebacks from bottom to top — the last line has the error type and the line above it has the failing code
  • Use the logging module instead of print() for any project larger than a single script
  • Catch specific exception types (KeyError, ValueError) not bare except clauses
  • Include the failing data in your log messages so you can reproduce the issue
  • Set logging level to DEBUG during development and WARNING in production
  • Use logging.exception() inside except blocks — it automatically includes the full traceback
  • Check the Console tab (not just Shell) when running your app with the Run button to see structured output

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

My Python script in Replit is crashing with a traceback. How do I read the traceback to find the error, add proper try/except error handling, and set up the logging module to track errors with timestamps? Give me a complete example.

Replit Prompt

This Python script is throwing errors. Add try/except error handling around the risky operations, set up the logging module with timestamps and severity levels, and make sure errors are logged with full context instead of crashing the app.

Frequently asked questions

When you press the Run button, Python errors (tracebacks) appear in the Console tab. If you run scripts manually in the Shell tab, errors appear in Shell output. Client-side JavaScript errors appear only in the Preview's browser DevTools, not the Console.

The Console shows output from the Run button with structured entries (stdout, stderr, status). The Shell is an interactive terminal where you can run commands directly. For debugging, the Console is best for running your app; Shell is best for running individual test commands.

Yes. Paste the traceback into the Agent chat and ask: 'This script is throwing this error. Fix the bug and add error handling so it does not crash.' Agent v4 will read the traceback, locate the issue, and apply a fix.

Check the Logs tab in the Deployments pane. All print() and logging output from your deployed app appears there. If logging is not set up, add the logging module so errors are captured with timestamps and context.

Replit does not include a step-through visual debugger like VS Code's Debug panel as of March 2026. You debug using Console output, print statements, and the logging module. For step-through debugging, use Python's built-in pdb by adding 'import pdb; pdb.set_trace()' in your code and running from Shell.

The Run button uses the command defined in the .replit file's run key, which may point to a different file or use different arguments than what you typed in Shell. Check your .replit file to verify the entrypoint and run command match what you expect.

If standard debugging approaches are not resolving the issue, the RapidDev engineering team can review your code, identify root causes, and implement fixes for complex Python errors that go beyond simple traceback reading.

logging.exception() logs a message at ERROR level and automatically appends the current exception's traceback. Use it inside except blocks when you want to log both your custom message and the full stack trace. It is equivalent to logging.error(msg, exc_info=True).

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.