The first cold mornings of November bring the same question every year: the outdoor unit of a heat pump is white with frost. Is that normal, or is it broken?
The answer is a short decision list, and a decision list is easy to write as code. This post turns the checks from HVAC Fitter's heat pump iced up guide into a function you can read top to bottom. It's a toy for learning, not a repair tool.
The facts the code encodes
From the guide (updated Oct 22, 2026):
- Light white frost is normal when it's near freezing outside. Moisture sticks to the cold coil, and the defrost cycle clears it.
- Thick ice or a solid block is not normal. Airflow stops and heating drops fast.
- During defrost, the unit briefly runs in cooling mode and the outdoor fan usually stops. So a still fan during defrost is expected. A fan that won't spin while heating is not.
- A fan that hums but won't spin often points to a bad capacitor rather than a dead motor.
- Ice that stays for days points to the defrost control board.
- A clogged indoor filter can disrupt the cycle too. Most filters need changing every 1 to 3 months.
- Refrigerant work needs an EPA Section 608 certified tech. That's always the last branch.
The function
from dataclasses import dataclass
@dataclass
class Observation:
ice: str # "none", "light frost", "thick ice" or "solid block"
hours_iced: float # how long the ice has stayed
outdoor_fan_spinning: bool # while the unit is heating (not during defrost)
fan_hums: bool # you hear a hum but the blades don't turn
filter_age_months: float # months since the indoor filter was changed
def triage(o: Observation) -> list[str]:
steps = []
if o.ice in ("none", "light frost"):
return ["Normal. Light frost is standard near freezing; the defrost cycle clears it."]
if o.filter_age_months >= 3:
steps.append("Replace the indoor air filter (most need it every 1 to 3 months).")
if not o.outdoor_fan_spinning:
if o.fan_hums:
steps.append("Fan hums but won't spin: suspect the run capacitor before the motor.")
else:
steps.append("Fan dead: check the motor; a replacement must match HP, volts and rotation.")
if o.hours_iced >= 48:
steps.append("Ice that stays for days: suspect the defrost control board.")
steps.append("Still iced after that, or any refrigerant question: call a licensed tech.")
return steps
if __name__ == "__main__":
cases = {
"frosty morning": Observation("light frost", 1, True, False, 1),
"old filter": Observation("thick ice", 6, True, False, 5),
"humming fan": Observation("thick ice", 30, False, True, 1),
"solid block": Observation("solid block", 48, True, False, 2),
}
for name, obs in cases.items():
print(f"{name}:")
for s in triage(obs):
print(" -", s)
Output
frosty morning:
- Normal. Light frost is standard near freezing; the defrost cycle clears it.
old filter:
- Replace the indoor air filter (most need it every 1 to 3 months).
- Still iced after that, or any refrigerant question: call a licensed tech.
humming fan:
- Fan hums but won't spin: suspect the run capacitor before the motor.
- Still iced after that, or any refrigerant question: call a licensed tech.
solid block:
- Ice that stays for days: suspect the defrost control board.
- Still iced after that, or any refrigerant question: call a licensed tech.
Why the order matters
The checks run cheapest-first. A filter costs a few dollars and takes a minute, so it comes before anything electrical. The "call a licensed tech" line is never skipped. Every frozen case ends there if the easy fixes don't work.
Two things the code doesn't try to do:
- It doesn't tell you to open the unit. The guide's safety rules come first: power off at the breaker and the outdoor disconnect, test for power, and remember that a capacitor can hold a charge with the power off. If that isn't you, stop and call a pro.
- It doesn't name a part. If the fan hums, the next step is reading the capacitor label and matching it. See which capacitor do I need. A replacement fan motor must match horsepower, voltage and rotation.
Try extending it
- Add a
defrost_runningflag so a still fan during defrost returns "normal". - Return objects with a
costandneeds_profield, then sort by them. - Write tests for the four cases above with
pytest.
If you'd rather check with a person than a function, the full guide has the thaw steps and the part lists: hvacfitter.com/guides/heat-pump-iced-up.
Top comments (0)