Line numbers refer to Datto-RMM/scripts/InstallHuntress.dattormm.comstore.ps1 at main (1089 lines).
copyLogAndExit is the terminal call on every path through the script, and it ends unconditionally with exit 0:
function copyLogAndExit {
...
Write-Output "Script complete"
exit 0
}
It is reached from the normal success path, from runProcess on a process timeout, from logInfo when connectivity checks fail, from the repair path, and from the script-level catch that handles every throw raised anywhere in the script:
try {
main
} catch {
$ErrorMessage = $_.Exception.Message
LogMessage $ErrorMessage
copyLogAndExit
}
The result is that no failure condition produces a non-zero exit code — not a failed download after all six retries, not an installer timeout, not a missing service, not a thrown validation error. From an RMM perspective every run is a green job, and the only way to detect failure is to parse stdout for strings like Script Failed! or ERROR:. That is brittle (the strings aren't stable or centrally defined) and it means monitoring and alerting can't be built on component exit status, which is the normal mechanism.
For MSP deployments at scale this matters more than it might appear: a silent-failure mode combined with a success exit code means uncovered endpoints don't surface anywhere until someone reconciles agent counts against the RMM inventory by hand.
A related instance of the same pattern is the empty conditional body at line 1019:
if ($repair) {
if (Test-Path(getAgentPath)){
if (!(repairAgent)){
} else {
LogMessage "Repair complete!"
}
copyLogAndExit
}
repairAgent returns $false when the Huntress Agent or Updater service is missing entirely — a state its own log messages describe as requiring an uninstall and reinstall to maintain security coverage. The false branch is empty, so nothing is logged at that level, and the script still exits 0.
Suggested change: add an optional exit code parameter to copyLogAndExit (defaulting to 0) and pass a non-zero value from error paths and from the script-level catch. Also log an explicit failure message in the repairAgent false branch rather than leaving the block empty.
I recognize a change to exit-code behavior could affect partners who have built tooling around the current always-zero behavior, so it may warrant a version bump note rather than a silent change.
Line numbers refer to
Datto-RMM/scripts/InstallHuntress.dattormm.comstore.ps1atmain(1089 lines).copyLogAndExitis the terminal call on every path through the script, and it ends unconditionally withexit 0:It is reached from the normal success path, from
runProcesson a process timeout, fromlogInfowhen connectivity checks fail, from the repair path, and from the script-levelcatchthat handles everythrowraised anywhere in the script:The result is that no failure condition produces a non-zero exit code — not a failed download after all six retries, not an installer timeout, not a missing service, not a thrown validation error. From an RMM perspective every run is a green job, and the only way to detect failure is to parse stdout for strings like
Script Failed!orERROR:. That is brittle (the strings aren't stable or centrally defined) and it means monitoring and alerting can't be built on component exit status, which is the normal mechanism.For MSP deployments at scale this matters more than it might appear: a silent-failure mode combined with a success exit code means uncovered endpoints don't surface anywhere until someone reconciles agent counts against the RMM inventory by hand.
A related instance of the same pattern is the empty conditional body at line 1019:
repairAgentreturns$falsewhen the Huntress Agent or Updater service is missing entirely — a state its own log messages describe as requiring an uninstall and reinstall to maintain security coverage. Thefalsebranch is empty, so nothing is logged at that level, and the script still exits 0.Suggested change: add an optional exit code parameter to
copyLogAndExit(defaulting to 0) and pass a non-zero value from error paths and from the script-levelcatch. Also log an explicit failure message in therepairAgentfalse branch rather than leaving the block empty.I recognize a change to exit-code behavior could affect partners who have built tooling around the current always-zero behavior, so it may warrant a version bump note rather than a silent change.