Python / Editorial solution guide

Resolve TypeError, unexpected None, and conversion failures

Trace the actual value to its origin, separate conversion from validation, and repair the contract that introduced the wrong type.

About 4 min readContent reviewed

Read-only knowledge base ยท No public comments

Recognize the symptoms

Arithmetic or concatenation raises TypeError, a lookup attempts to use None as a container, or int raises ValueError for external text. The visible failure can occur several calls after the wrong value was created.

A function that prints the correct number can still return None. A list operation such as sort mutates a list in place and also returns None, which often explains an unexpected assignment result.

Understand the likely causes

  • Common causes are mixing text and numbers, forgetting return on one branch, assigning the result of an in-place mutator, or assuming that annotations enforce runtime types.
  • Conversion and validation are distinct: "3" can be parsed, "many" cannot, and "-3" parses successfully but can violate a nonnegative quantity rule.

1. Trace the failing value to its producer

Read the exact exception and identify the operation and operand types. Inspect a small safe representation or type name locally, avoiding sensitive full records. Work backward through assignments and return statements until the first value violates the intended contract. Do not immediately apply str to everything: that can turn a missing numeric result into the literal text "None" and hide the real defect. Reduce the input to the smallest case that still shows the mismatch.

2. Repair missing results and in-place assumptions

Check every function path for a returned value when callers require one. Printing is an output effect rather than a substitute for return. For collections, choose between mutating an existing list with sort and obtaining a new sorted list with sorted. Do not assign items = items.sort(). The complete example preserves the original list and gives the new list a distinct name, making ownership clear. A failed later operation should be repaired at this producer, rather than patched with a distant default that silently changes the meaning of missing data.

python Preserve a collection and return a calculation
items = [3, 1, 2]
ordered = sorted(items)
print(items)
print(ordered)

def double(value):
    return value * 2

print(double(4))
Expected output
[3, 1, 2]
[1, 2, 3]
8

sorted returns a new list; the original order remains intact. The function explicitly returns eight rather than merely printing inside its body.

3. Parse external text, then validate its meaning

Treat input() and parsed CSV fields as text unless an explicit conversion has occurred. Surround the conversion itself with a narrow ValueError handler, then check domain constraints outside it. Decide whether empty text is missing, invalid, or a documented default; do not infer that policy from truthiness. The next example handles fixed synthetic strings, reports malformed text separately from a negative quantity, and never executes input as code. Real boundaries should also limit input length and preserve only safe diagnostic context. A conversion failure is expected bad data, while an unrelated TypeError inside domain logic may be a programming defect.

python Separate conversion and range checks
def parse_quantity(text):
    try:
        value = int(text)
    except ValueError as error:
        raise ValueError("expected integer text") from error
    if value < 0:
        raise ValueError("quantity must be nonnegative")
    return value

for text in ["3", "many", "-3"]:
    try:
        print(parse_quantity(text))
    except ValueError as error:
        print(error)
Expected output
3
expected integer text
quantity must be nonnegative

The valid case produces an integer. The malformed case fails parsing, while the negative case parses but fails the domain rule.

4. Make absence an explicit case

If None is a valid result, document it and branch with value is None before numeric or collection operations. Do not use if not value when zero or an empty collection is a valid distinct result. If None is never allowed, fix the missing return or rejected producer state instead of accepting it downstream. Avoid broad exception handlers that substitute zero for every failure: a genuine zero total and a failed calculation must remain distinguishable. Add focused regression cases for the path that previously returned the wrong type.

Verify the fix

The original minimal failing case now returns the documented type and value. Repeat a valid value, zero, a negative value, malformed text, and a legitimate missing-value case if the contract supports one.

Confirm that successful calculations remain numeric, every required return path is covered, and rejected input produces a clear expected error without being replaced by a plausible normal result.

Keep it from recurring

  • Keep parsing, domain calculations, and formatting separate. Document whether operations return a new value or mutate in place, and test every branch that promises a result.
  • Run static checking where configured, but retain runtime validation at external boundaries. Never use eval to make an input string act like a number.

Official references