diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
index 2fe39ac45c0e29758684078f106bb3077fffae58..f9fe677fd88f1eb1ae1d1f71e50a4647a6781743 100644
--- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
@@ -19,6 +19,9 @@ import purescala.Types._
 
 import scala.collection.mutable.{Map => MutableMap}
 
+case class UnsoundExtractionException(ast: Z3AST, msg: String)
+  extends Exception("Can't extract " + ast + " : " + msg)
+
 // This is just to factor out the things that are common in "classes that deal
 // with a Z3 instance"
 trait AbstractZ3Solver extends Solver {
@@ -34,6 +37,9 @@ trait AbstractZ3Solver extends Solver {
   private[this] var freed = false
   val traceE = new Exception()
 
+  protected def unsound(ast: Z3AST, msg: String): Nothing =
+    throw UnsoundExtractionException(ast, msg)
+
   override def finalize() {
     if (!freed) {
       println("!! Solver "+this.getClass.getName+"["+this.hashCode+"] not freed properly prior to GC:")
@@ -569,9 +575,7 @@ trait AbstractZ3Solver extends Solver {
                   case other =>
                     unsupported(other, "Unexpected target type for BV value")
                 }
-              case None => {
-                throw LeonFatalError(s"Could not translate hexadecimal Z3 numeral $t")
-              }
+              case None => unsound(t, "could not translate hexadecimal Z3 numeral")
             }
           } else {
             InfiniteIntegerLiteral(v)
@@ -583,12 +587,9 @@ trait AbstractZ3Solver extends Solver {
                 tpe match {
                   case Int32Type => IntLiteral(hexa.toInt)
                   case CharType  => CharLiteral(hexa.toInt.toChar)
-                  case _ =>
-                    throw LeonFatalError("Unexpected target type for BV value: " + tpe.asString)
+                  case _ => unsound(t, "unexpected target type for BV value: " + tpe.asString)
                 }
-            case None => {
-              throw LeonFatalError(s"Could not translate Z3NumeralIntAST numeral $t")
-            }
+            case None => unsound(t, "could not translate Z3NumeralIntAST numeral")
           }
         }
         case Z3NumeralRealAST(n: BigInt, d: BigInt) => FractionalLiteral(n, d)
@@ -626,12 +627,12 @@ trait AbstractZ3Solver extends Solver {
 
                     val entries = elems.map {
                       case (IntLiteral(i), v) => i -> v
-                      case _ => throw LeonFatalError("Translation from Z3 to Array failed")
+                      case (e,_) => unsupported(e, s"Z3 returned unexpected array index ${e.asString}")
                     }
 
                     finiteArray(entries, Some(default, s), to)
-                  case _ =>
-                    throw LeonFatalError("Translation from Z3 to Array failed")
+                  case (s : IntLiteral, arr) => unsound(args(1), "invalid array type")
+                  case (size, _) => unsound(args(0), "invalid array size")
                 }
             }
           } else {
@@ -645,7 +646,7 @@ trait AbstractZ3Solver extends Solver {
                     }
 
                     RawArrayValue(from, entries, default)
-                  case None => throw LeonFatalError("Translation from Z3 to Array failed")
+                  case None => unsound(t, "invalid array AST")
                 }
 
               case tp: TypeParameter =>
@@ -679,7 +680,7 @@ trait AbstractZ3Solver extends Solver {
 
               case tpe @ SetType(dt) =>
                 model.getSetValue(t) match {
-                  case None => throw LeonFatalError("Translation from Z3 to set failed")
+                  case None => unsound(t, "invalid set AST")
                   case Some(set) =>
                     val elems = set.map(e => rec(e, dt))
                     FiniteSet(elems, dt)
@@ -709,8 +710,7 @@ trait AbstractZ3Solver extends Solver {
             //      case OpDiv =>     Division(rargs(0), rargs(1))
             //      case OpIDiv =>    Division(rargs(0), rargs(1))
             //      case OpMod =>     Modulo(rargs(0), rargs(1))
-                  case other =>
-                    throw LeonFatalError(
+                  case other => unsound(t, 
                       s"""|Don't know what to do with this declKind: $other
                           |Expected type: ${Option(tpe).map{_.asString}.getOrElse("")}
                           |Tree: $t
@@ -719,8 +719,7 @@ trait AbstractZ3Solver extends Solver {
                 }
             }
           }
-        case _ =>
-          throw LeonFatalError(s"Don't know what to do with this Z3 tree: $t")
+        case _ => unsound(t, "unexpected AST")
       }
     }
     rec(tree, tpe)
@@ -731,6 +730,8 @@ trait AbstractZ3Solver extends Solver {
       Some(fromZ3Formula(model, tree, tpe))
     } catch {
       case e: Unsupported => None
+      case e: UnsoundExtractionException => None
+      case n: java.lang.NumberFormatException => None
     }
   }
 
diff --git a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
index a187549c514cc8fc83ec7476493e1d9e96a48763..c129243d15b661d9e42d578447fdea6cb1aea3e0 100644
--- a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
@@ -65,26 +65,14 @@ class FairZ3Solver(val context: LeonContext, val program: Program)
       val optEnabler = model.evalAs[Boolean](b)
 
       if (optEnabler == Some(true)) {
-        // FIXME: Dirty hack!
-        // Unfortunately, blockers don't lead to a true decision tree where all
-        // unexecutable branches are false since we have
-        //   b1 ==> ( b2 \/  b3)
-        //   b1 ==> (!b2 \/ !b3)
-        // so b2 /\ b3 is possible when b1 is false. This leads to unsound models
-        // (like Nil.tail) which obviously cannot be part of a domain but can't be
-        // translated back from Z3 either.
-        try {
-          val optArgs = (m.args zip fromTypes).map {
-            p => softFromZ3Formula(model, model.eval(Matcher.argValue(p._1), true).get, p._2)
-          }
+        val optArgs = (m.args zip fromTypes).map {
+          p => softFromZ3Formula(model, model.eval(Matcher.argValue(p._1), true).get, p._2)
+        }
 
-          if (optArgs.forall(_.isDefined)) {
-            Set(optArgs.map(_.get))
-          } else {
-            Set.empty
-          }
-        } catch {
-          case _: Throwable => Set.empty
+        if (optArgs.forall(_.isDefined)) {
+          Set(optArgs.map(_.get))
+        } else {
+          Set.empty
         }
       } else {
         Set.empty