Cataloging Common Integration Mistakes and Fixes
๐ท๏ธ Final Capstone Engineer Script project / Debugging Techniques
๐งญ Context Introduction
When connecting different systems, APIs, or services together, things don't always go as planned. Even a well-written script can fail due to small but critical integration mistakes. This guide catalogs the most frequent errors engineers encounter during integration work and provides straightforward fixes. Understanding these patterns will save you hours of debugging and help you build more resilient connections between components.
โ๏ธ Mistake #1: Ignoring Response Status Codes
The Problem: Many engineers assume an API call succeeded because no error was thrown. In reality, the server may have returned a 400 Bad Request or 500 Internal Server Error, but the script continued processing as if everything was fine.
The Fix: Always check the HTTP status code before processing the response. A successful response typically falls in the 200โ299 range. Anything outside that range should trigger a specific handling path. Log the status code and response body together so you can trace what went wrong.
Quick Tip: Treat every API response as potentially invalid until you explicitly verify its status code.
๐ ๏ธ Mistake #2: Hardcoding Configuration Values
The Problem: Credentials, endpoints, and environment-specific values are written directly into the script. When moving from development to staging or production, the script breaks because the hardcoded values no longer match.
The Fix: Store all configurable values in environment variables or a dedicated configuration file. Reference these values using a consistent naming convention. This makes your script portable across environments without modifying the code itself.
Quick Tip: Use a .env file for local development and inject environment variables through your deployment system for production.
๐ต๏ธ Mistake #3: Not Handling Timeouts Properly
The Problem: External services can be slow or unresponsive. Without a timeout setting, your script may hang indefinitely, blocking other processes and wasting resources.
The Fix: Set explicit timeout values for every external call. Choose a timeout that is generous enough for normal operation but aggressive enough to fail fast when something is wrong. Combine this with a retry mechanism for transient failures.
Quick Tip: A common pattern is 3 retries with exponential backoff (wait 1 second, then 2 seconds, then 4 seconds between attempts).
๐ Mistake #4: Assuming Data Format Consistency
The Problem: Engineers expect data to arrive in a specific format (e.g., JSON with certain field names), but the actual response may have missing fields, different data types, or unexpected null values.
The Fix: Validate the structure and types of incoming data before processing it. Check for required fields, verify data types (string vs. integer vs. null), and handle missing values gracefully. Use default values where appropriate.
Quick Tip: Create a simple validation function that checks each expected field and logs warnings for unexpected data shapes.
๐ Mistake #5: Forgetting to Close Connections
The Problem: Database connections, file handles, and network sockets remain open after use. Over time, this leads to resource exhaustion and mysterious failures.
The Fix: Always close connections explicitly when you are done with them. Better yet, use context managers that automatically handle cleanup, even if an error occurs during processing.
Quick Tip: For database connections and file operations, use the with statement pattern. It guarantees cleanup regardless of success or failure.
๐ Comparison Table: Common Mistakes vs. Best Practices
| โ Common Mistake | โ Best Practice | ๐ฏ Key Benefit |
|---|---|---|
| Ignoring status codes | Always verify response status | Catches silent failures early |
| Hardcoding values | Use environment variables | Script works across environments |
| No timeout handling | Set explicit timeouts with retries | Prevents hanging processes |
| Assuming data format | Validate structure and types | Handles unexpected data gracefully |
| Leaving connections open | Use context managers | Prevents resource leaks |
๐งช Mistake #6: Overlooking Authentication Expiry
The Problem: API tokens, session keys, and certificates have expiration dates. A script that worked yesterday fails today because the authentication credentials are no longer valid.
The Fix: Implement token refresh logic that checks expiration before making requests. If a token is about to expire, refresh it automatically. Log authentication failures separately so you can distinguish between credential issues and other errors.
Quick Tip: Store the token expiry timestamp alongside the token itself, and check it before each API call.
๐ Mistake #7: Swallowing Exceptions Silently
The Problem: A broad exception handler catches all errors but does nothing with them. The script continues running, but the error goes unnoticed until a downstream process fails mysteriously.
The Fix: Never use empty exception handlers. At minimum, log the error with its full traceback. For critical failures, consider stopping the process or sending an alert. Be specific about which exceptions you catch.
Quick Tip: Log exceptions with different severity levels. Use WARNING for recoverable issues and ERROR for failures that require human attention.
๐ Mistake #8: Mixing Synchronous and Asynchronous Calls Incorrectly
The Problem: Engineers combine blocking synchronous calls with asynchronous code, causing performance bottlenecks or deadlocks. The script becomes unpredictable and hard to debug.
The Fix: Choose one paradigm and stick with it. If you are using asynchronous code, make sure all I/O operations are non-blocking. If you are using synchronous code, avoid mixing in async functions without proper handling.
Quick Tip: Use dedicated libraries designed for your chosen paradigm. For async work, use aiohttp or httpx. For sync work, use requests.
๐งฉ Final Thoughts
Integration mistakes are a normal part of building connected systems. The key is to recognize these patterns early and apply consistent fixes. By checking status codes, using configuration files, setting timeouts, validating data, managing connections, handling authentication, logging exceptions, and choosing the right execution model, you can avoid the most common pitfalls.
Remember: every integration failure is a learning opportunity. Document what went wrong and how you fixed it. Over time, you will build a personal catalog of patterns that make your scripts more robust and reliable.
This file catalogs common mistakes engineers make when integrating Python code with external systems and shows how to fix them.
๐ง Example 1: Forgetting to convert string numbers to integers
This example shows what happens when you try to add a string number to an integer without conversion.
sensor_reading = "42"
offset = 8
# Mistake: adding string to integer
result = sensor_reading + offset
๐ค Output: TypeError: can only concatenate str (not "int") to str
๐ง Example 2: Fixing string-to-integer conversion
This example shows how to properly convert a string number to an integer before performing arithmetic.
sensor_reading = "42"
offset = 8
# Fix: convert string to integer first
reading_int = int(sensor_reading)
result = reading_int + offset
print(result)
๐ค Output: 50
๐ง Example 3: Missing file path when reading configuration
This example shows what happens when you try to open a file that does not exist at the given path.
config_path = "settings.txt"
# Mistake: file does not exist at this path
config_file = open(config_path, "r")
content = config_file.read()
config_file.close()
๐ค Output: FileNotFoundError: [Errno 2] No such file or directory: 'settings.txt'
๐ง Example 4: Using try-except to handle missing files gracefully
This example shows how to safely attempt to read a file and handle the case where it is missing.
config_path = "settings.txt"
try:
config_file = open(config_path, "r")
content = config_file.read()
config_file.close()
print("Configuration loaded")
except FileNotFoundError:
print("Using default settings")
๐ค Output: Using default settings
๐ง Example 5: Forgetting to close a database connection
This example shows what happens when you leave a database connection open after querying data.
import sqlite3
connection = sqlite3.connect("inventory.db")
cursor = connection.cursor()
cursor.execute("SELECT * FROM parts")
results = cursor.fetchall()
# Mistake: no connection.close() called
print(results)
๐ค Output: [(1, 'bolt', 0.50), (2, 'nut', 0.25)] (connection remains open)
๐ง Example 6: Properly closing a database connection with a context manager
This example shows how to use a with block to automatically close the database connection.
import sqlite3
with sqlite3.connect("inventory.db") as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM parts")
results = cursor.fetchall()
print(results)
๐ค Output: [(1, 'bolt', 0.50), (2, 'nut', 0.25)] (connection closed automatically)
๐ง Example 7: Passing wrong data type to an API function
This example shows what happens when you pass a list instead of a string to a function expecting text.
def send_message(text):
print(f"Sending: {text}")
message_parts = ["Temperature", ":", " 85F"]
# Mistake: passing list instead of string
send_message(message_parts)
๐ค Output: Sending: ['Temperature', ':', ' 85F'] (function receives list, not string)
๐ง Example 8: Fixing data type mismatch with string join
This example shows how to combine list elements into a single string before passing to the function.
def send_message(text):
print(f"Sending: {text}")
message_parts = ["Temperature", ":", " 85F"]
# Fix: join list into a single string
full_message = "".join(message_parts)
send_message(full_message)
๐ค Output: Sending: Temperature: 85F
Comparison Table: Common Integration Mistakes and Fixes
| Mistake | Problem | Fix |
|---|---|---|
| Adding string to integer | Type error | Convert string with int() |
| Opening missing file | File not found error | Use try-except block |
| Leaving database open | Resource leak | Use with context manager |
| Passing wrong data type | Function receives unexpected type | Convert with join() or str() |
| Not handling network timeout | Script hangs forever | Set timeout parameter |
๐งญ Context Introduction
When connecting different systems, APIs, or services together, things don't always go as planned. Even a well-written script can fail due to small but critical integration mistakes. This guide catalogs the most frequent errors engineers encounter during integration work and provides straightforward fixes. Understanding these patterns will save you hours of debugging and help you build more resilient connections between components.
โ๏ธ Mistake #1: Ignoring Response Status Codes
The Problem: Many engineers assume an API call succeeded because no error was thrown. In reality, the server may have returned a 400 Bad Request or 500 Internal Server Error, but the script continued processing as if everything was fine.
The Fix: Always check the HTTP status code before processing the response. A successful response typically falls in the 200โ299 range. Anything outside that range should trigger a specific handling path. Log the status code and response body together so you can trace what went wrong.
Quick Tip: Treat every API response as potentially invalid until you explicitly verify its status code.
๐ ๏ธ Mistake #2: Hardcoding Configuration Values
The Problem: Credentials, endpoints, and environment-specific values are written directly into the script. When moving from development to staging or production, the script breaks because the hardcoded values no longer match.
The Fix: Store all configurable values in environment variables or a dedicated configuration file. Reference these values using a consistent naming convention. This makes your script portable across environments without modifying the code itself.
Quick Tip: Use a .env file for local development and inject environment variables through your deployment system for production.
๐ต๏ธ Mistake #3: Not Handling Timeouts Properly
The Problem: External services can be slow or unresponsive. Without a timeout setting, your script may hang indefinitely, blocking other processes and wasting resources.
The Fix: Set explicit timeout values for every external call. Choose a timeout that is generous enough for normal operation but aggressive enough to fail fast when something is wrong. Combine this with a retry mechanism for transient failures.
Quick Tip: A common pattern is 3 retries with exponential backoff (wait 1 second, then 2 seconds, then 4 seconds between attempts).
๐ Mistake #4: Assuming Data Format Consistency
The Problem: Engineers expect data to arrive in a specific format (e.g., JSON with certain field names), but the actual response may have missing fields, different data types, or unexpected null values.
The Fix: Validate the structure and types of incoming data before processing it. Check for required fields, verify data types (string vs. integer vs. null), and handle missing values gracefully. Use default values where appropriate.
Quick Tip: Create a simple validation function that checks each expected field and logs warnings for unexpected data shapes.
๐ Mistake #5: Forgetting to Close Connections
The Problem: Database connections, file handles, and network sockets remain open after use. Over time, this leads to resource exhaustion and mysterious failures.
The Fix: Always close connections explicitly when you are done with them. Better yet, use context managers that automatically handle cleanup, even if an error occurs during processing.
Quick Tip: For database connections and file operations, use the with statement pattern. It guarantees cleanup regardless of success or failure.
๐ Comparison Table: Common Mistakes vs. Best Practices
| โ Common Mistake | โ Best Practice | ๐ฏ Key Benefit |
|---|---|---|
| Ignoring status codes | Always verify response status | Catches silent failures early |
| Hardcoding values | Use environment variables | Script works across environments |
| No timeout handling | Set explicit timeouts with retries | Prevents hanging processes |
| Assuming data format | Validate structure and types | Handles unexpected data gracefully |
| Leaving connections open | Use context managers | Prevents resource leaks |
๐งช Mistake #6: Overlooking Authentication Expiry
The Problem: API tokens, session keys, and certificates have expiration dates. A script that worked yesterday fails today because the authentication credentials are no longer valid.
The Fix: Implement token refresh logic that checks expiration before making requests. If a token is about to expire, refresh it automatically. Log authentication failures separately so you can distinguish between credential issues and other errors.
Quick Tip: Store the token expiry timestamp alongside the token itself, and check it before each API call.
๐ Mistake #7: Swallowing Exceptions Silently
The Problem: A broad exception handler catches all errors but does nothing with them. The script continues running, but the error goes unnoticed until a downstream process fails mysteriously.
The Fix: Never use empty exception handlers. At minimum, log the error with its full traceback. For critical failures, consider stopping the process or sending an alert. Be specific about which exceptions you catch.
Quick Tip: Log exceptions with different severity levels. Use WARNING for recoverable issues and ERROR for failures that require human attention.
๐ Mistake #8: Mixing Synchronous and Asynchronous Calls Incorrectly
The Problem: Engineers combine blocking synchronous calls with asynchronous code, causing performance bottlenecks or deadlocks. The script becomes unpredictable and hard to debug.
The Fix: Choose one paradigm and stick with it. If you are using asynchronous code, make sure all I/O operations are non-blocking. If you are using synchronous code, avoid mixing in async functions without proper handling.
Quick Tip: Use dedicated libraries designed for your chosen paradigm. For async work, use aiohttp or httpx. For sync work, use requests.
๐งฉ Final Thoughts
Integration mistakes are a normal part of building connected systems. The key is to recognize these patterns early and apply consistent fixes. By checking status codes, using configuration files, setting timeouts, validating data, managing connections, handling authentication, logging exceptions, and choosing the right execution model, you can avoid the most common pitfalls.
Remember: every integration failure is a learning opportunity. Document what went wrong and how you fixed it. Over time, you will build a personal catalog of patterns that make your scripts more robust and reliable.
Interactive Views
You are currently in ๐ All-in-One mode. Use the tabs at the top to switch to ๐ Theory Only or ๐ป Code Only views.
This file catalogs common mistakes engineers make when integrating Python code with external systems and shows how to fix them.
๐ง Example 1: Forgetting to convert string numbers to integers
This example shows what happens when you try to add a string number to an integer without conversion.
sensor_reading = "42"
offset = 8
# Mistake: adding string to integer
result = sensor_reading + offset
๐ค Output: TypeError: can only concatenate str (not "int") to str
๐ง Example 2: Fixing string-to-integer conversion
This example shows how to properly convert a string number to an integer before performing arithmetic.
sensor_reading = "42"
offset = 8
# Fix: convert string to integer first
reading_int = int(sensor_reading)
result = reading_int + offset
print(result)
๐ค Output: 50
๐ง Example 3: Missing file path when reading configuration
This example shows what happens when you try to open a file that does not exist at the given path.
config_path = "settings.txt"
# Mistake: file does not exist at this path
config_file = open(config_path, "r")
content = config_file.read()
config_file.close()
๐ค Output: FileNotFoundError: [Errno 2] No such file or directory: 'settings.txt'
๐ง Example 4: Using try-except to handle missing files gracefully
This example shows how to safely attempt to read a file and handle the case where it is missing.
config_path = "settings.txt"
try:
config_file = open(config_path, "r")
content = config_file.read()
config_file.close()
print("Configuration loaded")
except FileNotFoundError:
print("Using default settings")
๐ค Output: Using default settings
๐ง Example 5: Forgetting to close a database connection
This example shows what happens when you leave a database connection open after querying data.
import sqlite3
connection = sqlite3.connect("inventory.db")
cursor = connection.cursor()
cursor.execute("SELECT * FROM parts")
results = cursor.fetchall()
# Mistake: no connection.close() called
print(results)
๐ค Output: [(1, 'bolt', 0.50), (2, 'nut', 0.25)] (connection remains open)
๐ง Example 6: Properly closing a database connection with a context manager
This example shows how to use a with block to automatically close the database connection.
import sqlite3
with sqlite3.connect("inventory.db") as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM parts")
results = cursor.fetchall()
print(results)
๐ค Output: [(1, 'bolt', 0.50), (2, 'nut', 0.25)] (connection closed automatically)
๐ง Example 7: Passing wrong data type to an API function
This example shows what happens when you pass a list instead of a string to a function expecting text.
def send_message(text):
print(f"Sending: {text}")
message_parts = ["Temperature", ":", " 85F"]
# Mistake: passing list instead of string
send_message(message_parts)
๐ค Output: Sending: ['Temperature', ':', ' 85F'] (function receives list, not string)
๐ง Example 8: Fixing data type mismatch with string join
This example shows how to combine list elements into a single string before passing to the function.
def send_message(text):
print(f"Sending: {text}")
message_parts = ["Temperature", ":", " 85F"]
# Fix: join list into a single string
full_message = "".join(message_parts)
send_message(full_message)
๐ค Output: Sending: Temperature: 85F
Comparison Table: Common Integration Mistakes and Fixes
| Mistake | Problem | Fix |
|---|---|---|
| Adding string to integer | Type error | Convert string with int() |
| Opening missing file | File not found error | Use try-except block |
| Leaving database open | Resource leak | Use with context manager |
| Passing wrong data type | Function receives unexpected type | Convert with join() or str() |
| Not handling network timeout | Script hangs forever | Set timeout parameter |