When handling failures, ensure your code (a) raises the right exception to control exit code/automation, (b) doesn’t silently ignore user intent or skip required checks, and (c) produces parameter-aware, actionable messages.
Practical standards: 1) Explicit success/failure contract
2) Use precise, intentional exception types
3) Make messages context-rich and branch-correct
4) Avoid silent ignores and skipped validations
5) Defensive error detection
Example pattern (parallel execute with non-zero on failures):
results = run_parallel(...)
failed = [r for r in results if r.get('status') == 'failed']
if failed:
raise AzureResponseError(
f"Command execution failed on {len(failed)} of {len(results)} instance(s). "
"See the messages above for details."
)
return results # only when everything was accepted
Example pattern (404 messaging that depends on inputs):
if response.status_code == 404:
if instance:
raise CLIError(f"No startup logs found for instance '{instance}'. Run list to see available instances.")
logger.warning("Startup logs are not available for this app; feature may not be rolled out yet.")
return []
Applying these consistently will make CLI behavior predictable for both humans and automation, and will prevent misleading/opaque failures.