Network Automation Fundamentals
Validation, Safety & Failure Handling
What you'll learn
- Why 'the command ran' and 'the change succeeded' are different claims
- The pre-check → change → post-check → validate pattern, and what each stage catches
- How to tell timeout, authentication failure, unreachable device, and command failure apart
- Why partial failure across many devices needs honest, separated reporting
- Why one device failing shouldn't necessarily stop automation from checking the rest
Listen to a guided explanation of this lesson.
Spoken narration isn't supported in this browser.
"It ran" is not "it worked"
This module has circled this idea a few times already — it's worth making it the center of its own lesson, because it's the single most common way automation goes wrong quietly. A command can execute cleanly, return no error, and still not mean the network change actually succeeded. show vlan brief returning output isn't proof the VLAN is correct. A no shutdown command completing isn't proof the interface came up. Execution succeeding tells you the device accepted the command. It says nothing about the outcome.
Safe automation is built around a pattern that closes this exact gap.
Pre-check, change, post-check, validate
- Pre-checkwhat's the state before touching anything?
- Changeapply the configuration change
- Post-checkwhat's the state after?
- Validatedoes post-check match what you expected?
Pre-check captures the state before anything happens — not busywork, but your baseline. If something looks wrong afterward, pre-check is how you know what "before" actually looked like, instead of guessing.
Change is the actual action: pushing the config, applying the update. This is the step most people think of as "the automation" — but on its own it's just execution, same as in the first lesson of this module.
Post-check re-inspects the device after the change — the same kind of check as pre-check, run again, to see what's actually true now.
Validate compares post-check against what you expected the change to produce. This is the step that turns "the command ran" into an actual answer to "did the change work?"
When the result doesn't match
Validation ends in one of two places, and good automation treats both as normal, expected outcomes — not just the "yes" path:
- Post-check
- Validatematches expected state
- Success
- Reportconfirmed working
- Post-check
- Validatedoesn't match expected state
- Investigate
- Reportflagged for review
Notice both paths end in a report — the difference is what the report says. A mismatch isn't a bug in the automation; it's exactly the situation validation exists to catch. The dangerous failure mode isn't "validation found a problem." It's automation that doesn't validate at all, and reports success either way.
The ways a device or command can fail
Not every failure looks the same, and telling them apart matters for what happens next:
- Timeout — the device didn't respond within the expected window. It might be overloaded, slow, or mid-reboot. Worth retrying, possibly worth investigating if it happens repeatedly.
- Authentication failure — the credentials were rejected. Wrong password, an expired account, or a TACACS+ server that's unreachable. This is not a device problem — retrying the same credentials won't fix it, and it needs a person's attention.
- Unreachable device — no response at all, typically because there's no network path (routing issue, ACL, the device is powered off). Different from a timeout: a timeout got a connection and waited too long for a reply; unreachable never got a connection in the first place.
- Command failure — the connection worked and the login succeeded, but the specific command was rejected: wrong syntax for that platform, insufficient privilege level, or issued in the wrong CLI mode (a config command sent while still in user exec mode, for example).
Where in the process each one shows up
Timeout, authentication failure, and unreachable device all happen before you ever get to run a command — they're connection-stage problems. Command failure happens after a session is already open, when the specific instruction itself doesn't succeed. Knowing which stage a failure came from tells you a lot about what to check first.
Partial failure: the normal outcome at scale
Run a change against 500 switches and the realistic outcome usually isn't "all 500 succeeded" or "it failed." It's something like: 480 succeeded, 12 had a command failure worth investigating, 5 were unreachable, and 3 timed out and should be retried. That's partial failure — and it's not a special edge case, it's the expected shape of most large automation runs.
Good reporting doesn't collapse that into one number. It separates outcomes by category — succeeded, command failure, unreachable, timeout — so the person reading the report knows exactly what needs attention and why, instead of a single "87% success" figure that hides four different problems needing four different responses.
One failing device shouldn't stop the other 499
If device 23 out of 500 is unreachable, that's a reason to flag device 23 — not a reason to abandon the run and leave the other 499 unchecked. Stopping everything over one failure throws away good information about every device that was fine. This is the same failure-handling principle from "Start Here," now with more than one failure category to sort into.
succeeded, unreachable, command_failed, mismatched = [], [], [], []
for switch in devices:
try:
session = connect(switch, timeout=5) # Pre-check / connect
except TimeoutError:
unreachable.append((switch, "timeout"))
continue
except UnreachableError:
unreachable.append((switch, "no route"))
continue
try:
session.send_command("interface vlan 20 ...") # Change
except CommandError as e:
command_failed.append((switch, str(e)))
continue
post_check = session.send_command("show vlan brief") # Post-check
if is_expected(post_check): # Validate
succeeded.append(switch)
else:
mismatched.append(switch)
send_report(succeeded, unreachable, command_failed, mismatched)Not a Python lesson — just a picture of the pattern. Notice each failure type lands in its own list instead of one generic 'failed' bucket, which is what lets the final report tell someone exactly what kind of attention each device needs.
Where this module leaves you
Across this module, you've gone from the seven pieces every automation task is built from, to what real inventory needs to look like, to the difference between configuration and state, to why automation has to check before it changes, and now to validating results and handling failure honestly instead of assuming success. That's the conceptual foundation this whole curriculum is built on — everything from here forward (starting with just enough Python to actually write these scripts) is about implementing these ideas, not learning new ones.
Key takeaways
- A command executing without error proves it ran — not that the network change actually succeeded. Validation is what checks the outcome itself.
- Safe changes follow pre-check → change → post-check → validate, so 'before' and 'after' are both real, observed states, not assumptions.
- Timeout, authentication failure, and unreachable device are connection-stage problems; command failure happens after a session is already open — telling them apart matters for what to do next.
- Partial failure — some devices succeed, some don't, for different reasons — is the normal outcome at scale, not an edge case.
- One device failing is a reason to flag that device, not a reason to stop checking every other one — and an honest report separates failure types instead of collapsing them into a single number.