When cancellation occurs everything in the library (including interceptors) is cleaned up by the time the application learns about it. So no, it wouldn't leak.
However, since StreamObservers generally expect that either onError/onCompleted will always be called, it isn't a bad idea to call onError(). This would be more important if you have a pipeline of many StreamObservers, something more akin to what happens in RxJava. I'm actually a bit surprised to see that StreamObserver doesn't mandate that onError/onCompleted will always be called. That sort of seems like an oversight.
On the other hand, calling onError() can be a major PITA in certain cases because you sometimes need to coordinate with another thread. The practical side of me would easily be like, "ain't nobody got time for that!" Granted, most frequently you are coordinating with that other thread anyway to stop its execution, so just having that thread call onError() as it stops is no big deal.
So all that is to say: I'd suggest "always" calling either onError/onCompleted as it makes the code more clear. But if you find a case that is a pain, it is likely prudent to ignore calling onError.