Update: 0.96.0 has been released. Update to that if you are still experiencing this problem.
Many of you may have noticed that with the Armory 0.95.1 and Bitcoin Core 0.14.0, Armory tends to fail to broadcast transactions and give the "Transaction timed out" and "Transaction broadcast failed" error messages.
The underlying issue that is causing this problem has been fixed for Armory 0.96, which will be released soon. However, in the meantime, downgrading to Bitcoin Core 0.13.2 will fix the issue. Once 0.96 is released, you will be able to use Bitcoin Core 0.14.0 again.
To downgrade to Bitcoin Core 0.13.2, just download the Bitcoin Core 0.13.2 binaries from
https://bitcoin.org/bin/bitcoin-core-0.13.2/ and install them as you would normally install a new version of Bitcoin Core. There is no need to redownload the blockchain nor reindex Bitcoin Core's databases nor rebuild Armory's databases.
Now for the technical details about the problem, for those of you who care.
I first noticed this issue back in December, but only very recently have I nailed down why this problem cropped up in the first place.
Bitcoin Core 0.14.0 merged a change back in December which changed how Bitcoin P2P messages were being broadcast. Previously, the p2p message header and the message payload were sent all at the same time using the same kernel call. However, during their net refactor and cleanup, this mechanism was
changed to send the message header in one call, and then the payload in a separate call. This is more robust and allows for better code separation, but it also causes problems for Armory.
The implementation in Armory 0.95.1 for receiving the p2p messages is not able to handle that the two parts of a p2p message are essentially sent separately. It interprets the message header as one p2p message, and the message payload as another p2p message. This means that it is incorrectly parsing the messages. The crux of the issue is that every so often Armory will receive a
ping message from Bitcoin Core. However the payload of the
ping message is only 8 bytes, but the message header must be 24 bytes. When Armory interprets the
ping payload as a separate message, it will throw an exception because it thinks the message is too short. This exception causes the data processing thread to exit and disconnect from Bitcoin Core. Once it disconnects, it will typically reconnect, but the reconnect does not always mean that it will actually be receiving new blocks and transactions and actually remaining up-to-date with the blockchain. Thus, because of this disconnect, when you go to send some Bitcoin, it will fail to either connect to Bitcoin Core or the reconnected connection is messed up and the transaction broadcast times out or just fails entirely.