How to check for None and raise helpful errors in Python
A defensive function that explicitly validates data, keys, and values — raising descriptive ValueError and KeyError exceptions before returning a result.
Python code
19 linesdef get_value(data, key):
if data is None:
raise ValueError("data cannot be None")
if key not in data:
raise KeyError(f"key '{key}' not found in data")
result = data[key]
if result is None:
raise ValueError(f"value for key '{key}' is None")
return result
if __name__ == "__main__":
sample = {"name": "Alice", "age": None}
for key in ("name", "age", "missing"):
try:
value = get_value(sample, key)
print(f"{key}: {value}")
except (ValueError, KeyError) as e:
print(f"{key}: ERROR: {e}")
Output
name: Alice
age: ERROR: value for key 'age' is None
missing: ERROR: key 'missing' not found in data
How it works
The get_value function runs three explicit checks: whether data itself is None, whether the requested key exists, and whether the associated value is None. Each failure raises a distinct exception with a human-readable message, making bugs easier to trace. Early returns and explicit raise statements keep the control flow simple and understandable. This pattern is deterministic and testable — no silent None propagation or unexpected KeyError deep in your call stack.
Common mistakes
- Forgetting to raise a custom message for clarity
- Checking values for None but not guarding against the data container itself
- Using `if data:` instead of `if data is None:` — empty dicts are falsy and would incorrectly raise
- Neglecting to handle the key-not-found case before the None-value check
Variations
- Use `data.get(key)` with a sentinel default and check if it's the sentinel to distinguish missing keys from None values
- Define a custom exception subclass (e.g., `MissingKeyError(KeyError)`) for more refined error handling by callers
Real-world use cases
- Validating user-provided config dictionaries before passing them to a connection pool or database engine.
- Wrapping a third-party API response dict so missing or null fields fail fast with readable errors.
- Sanitizing JSON payloads from webhooks or message queues before mapping them into internal models.
Sponsored
More from Errors & debugging
- Catch RecursionError and Fail Gracefully in Python easy
- Catch ValueError and print friendly message in Python easy
- Collect Multiple Validation Errors in Python Before Raising medium
- Handle ValueError and ZeroDivisionError in Python with try except easy
- How to Add a Correlation ID to Logging Records in Python medium
- How to Assert Preconditions with Descriptive Messages in Python easy
Keep learning
Related tutorials and quizzes for this topic.