The literal answer is no: TLS does not accept unencrypted messages. However, your colleague's worries are not unfounded. I don't know whether he's confused but accidentally stumbled onto a real concern, or he understands the issues but explained them very confusingly.
A TLS connection is always encrypted (so a man-in-the-middle cannot read the data that is transmitted) and integrity-protected (so a man-in-the-middle cannot modify the data that is transmitted¹). Although the TLS specification defines a “null” ciphersuite, most applications won't use it, and not all TLS libraries even alow it. Unless you go out of your way to enable it both on the client and the server side, the null ciphersuite won't happen. Every other ciphersuite has encryption and integrity protection.
The security of TLS also relies on the two parties ensuring that they're talking directly to each other. There would be no security if all that happened was that the legitimate client has a secure connection to the man-in-the-middle, and the man-in-the-middle has a secure connection to the legitimate server. The way this works on the web (and in most other uses of TLS) is that the client authenticates the server by verifying that the server's certificate is valid. I won't go into what “valid” means here; in a nutshell, the certificate has to be cryptographically consistent with the connection (the client will always verify this) and has to be signed by a certificate authority that the client trusts (this bit is a bit more fragile, but it'll work provided you use reasonably up-to-date software and set up the server properly).
As usual all of this is subject to keeping up with security updates in the software, and to configuring it properly. Some older versions of the protocol have been broken, i.e. they don't offer the guarantees that they were designed to offer. But as long as you don't run ancient software or enable obsolete features in the server configuration, things are fine.
So what might your colleague be referring to?
someone, someday, will forget to encrypt a message, expose their session token/user identity/whatever, and leave themselves open to a man-in-the-middle attack
This can happen even if your server supports TLS. A client could send an HTTP request instead of HTTPS. Then an attacker could impersonate your server and see the data that the client sent over HTTP. There's nothing the server can do to completely prevent this, but there are things you can do to make it mostly a moot issue.
The first thing to do is to only give people URLs starting with https://
. That doesn't help if people type the URL directly.
One side of the coin is to configure your server not to respond to HTTP, except to redirect to the HTTPS site. In other words, all you serve on port 80 are redirects to https://same remainder of the URL
. Furthermore, convey to the client that they should use HTTPS directly the next time, by enabling HSTS in your server's configuration. HSTS makes the server send the client an instruction to always use HTTPS for a particular site in the future. This way only the first connection from a particular client might be in cleartext.
The other side of the coin is to protect confidential data from being sent over HTTP. You can't protect the user's credentials if they insist on sending them in cleartext, just like you can't prevent a user from opening their window and shouting their password to everybody in the street. But you can protect the cookies that your application uses: make sure that all of your cookies have the secure
flag. That way, if the user somehow gets their browser to make an HTTP connection, the browser won't send the cookies.
¹ Exception: a mitm can force the connection to be closed midway. This is in principle visible because that happens at the TCP level and both parties can tell that the TLS level wasn't properly terminated (by a fatal alert), but applications such as browsers typically don't provide any feedback about this, and it's indistinguishable from network glitches that do happen.