The thing is that find returns not a User, but a Future[User].
Future[User] can be either DefaultPromise[User] or never.
Future's map(..) and recover(..) redirect to Try's map(..) and recover(..) via Future's transform(..). And the transform(..) is defined differently for both cases.
trait Future[+T] extends Awaitable[T] {
  def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = transform(_ map f)
  def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = 
    transform { _ recover pf }
  def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S]
  //...
}
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
  override def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S] = {
    val p = new DefaultPromise[S]()
    onComplete { result => p.complete(try f(result) catch { case NonFatal(t) => Failure(t) }) }
    p.future
  }
  //...
}
class DefaultPromise[T] extends AtomicReference[AnyRef](Nil) with Promise[T] { /*...*/ }
final object never extends Future[Nothing] {
  override def transform[S](f: Try[Nothing] => Try[S])(implicit executor: ExecutionContext): Future[S] = this
  //...
}
https://github.com/scala/scala/blob/2.13.x/src/library/scala/concurrent/Future.scala
Try[User] can be either Failure[User] or Success[User]. And map(..) and recover(..) are defined there differenty for both cases. 
sealed abstract class Try[+T] extends Product with Serializable {
  def map[U](f: T => U): Try[U]
  def recover[U >: T](@deprecatedName('f) pf: PartialFunction[Throwable, U]): Try[U]
  //...
}
final case class Failure[+T](exception: Throwable) extends Try[T] {
  override def map[U](f: T => U): Try[U] = this.asInstanceOf[Try[U]]
  override def recover[U >: T](@deprecatedName('rescueException) pf: PartialFunction[Throwable, U]): Try[U] =
    try { if (pf isDefinedAt exception) Success(pf(exception)) else this } catch { case NonFatal(e) => Failure(e) }
  //...
}
final case class Success[+T](value: T) extends Try[T] {
  override def map[U](f: T => U): Try[U] = Try[U](f(value))
  override def recover[U >: T](@deprecatedName('rescueException) pf: PartialFunction[Throwable, U]): Try[U] = this
  //...
}
https://github.com/scala/scala/blob/2.13.x/src/library/scala/util/Try.scala
So basically all cases are dealt with: 
- when 1st call is success (then 2nd call is trivial, you can see above that implementation of recover(..)forSuccessis trivially justthis)
- when 1st call is failure but 2nd is success
- when both calls are failures
Maybe you should read more about Try, Future and other monads, monadic chaining of calculations etc.
Error Handling With Try
Welcome to the Future
Promises and Futures in Practice
Futures and Promises