Previously nodetool repair would exit with a non-zero status code when it experienced an error (like in
CASSANDRA-5203), e.g. due a neighbor being down or a failed stream. It appears this is no longer the case, which makes it a bit harder to automate repair. I suspect it's been this way since CASSANDRA-6381 was implemented, and that it probably affects other nodetool commands as well.
It looks like NodeProbe tracks when a failure occurs and this is accessible via NodeProbe.isFailed(), but that value is not being used anywhere. I think the problem could be fixed inside NodeTool.NodeToolCmd.run(), if after the execute function is called, probe.isFailed() is checked and a RuntimeException is thrown if a failure has occurred.