diff --git a/src/plugins/server/data.ml b/src/plugins/server/data.ml
index 46c204d72366ee3e90f6160d5dbc61a078989eeb..796f4c54dce76dfcd7a8422f0e45706c55c44694 100644
--- a/src/plugins/server/data.ml
+++ b/src/plugins/server/data.ml
@@ -47,8 +47,21 @@ end
 
 type 'a data = (module S with type t = 'a)
 
-let failure js msg =
-  Pretty_utils.ksfprintf (fun msg -> raise(Ju.Type_error(msg,js))) msg
+exception InputError of string
+
+let failure ?json msg =
+  let add_json msg =
+    let msg = match json with
+      | None -> msg
+      | Some json ->
+        Format.asprintf "@[%s:@ %s@]" msg (Js.pretty_to_string json)
+    in
+    raise(InputError(msg))
+  in
+  Pretty_utils.ksfprintf add_json msg
+
+let failure_from_type_error msg json =
+  failure ~json "%s" msg
 
 (* -------------------------------------------------------------------------- *)
 (* --- Option                                                             --- *)
@@ -84,7 +97,7 @@ struct
   let to_json (x,y) = `List [ A.to_json x ; B.to_json y ]
   let of_json = function
     | `List [ ja ; jb ] -> A.of_json ja , B.of_json jb
-    | js -> failure js "Expected list with 2 elements"
+    | js -> failure ~json:js "Expected list with 2 elements"
 end
 
 module Jtriple(A : S)(B : S)(C : S) : S with type t = A.t * B.t * C.t =
@@ -94,7 +107,7 @@ struct
   let to_json (x,y,z) = `List [ A.to_json x ; B.to_json y ; C.to_json z ]
   let of_json = function
     | `List [ ja ; jb ; jc ] -> A.of_json ja , B.of_json jb , C.of_json jc
-    | js -> failure js "Expected list with 3 elements"
+    | js -> failure ~json:js "Expected list with 3 elements"
 end
 
 (* -------------------------------------------------------------------------- *)
@@ -354,7 +367,7 @@ struct
     let id = Ju.to_int js in
     try find m id
     with Not_found ->
-      failure js "[%s] No registered id #%d" I.name id
+      failure "[%s] No registered id #%d" I.name id
 
 end
 
@@ -453,7 +466,7 @@ struct
         let of_json js =
           let k = Ju.to_int js in
           try find k
-          with Not_found -> failure js "[%s] No registered id #%d" A.name k
+          with Not_found -> failure "[%s] No registered id #%d" A.name k
       end)
 
 end
diff --git a/src/plugins/server/data.mli b/src/plugins/server/data.mli
index f0c993fd042ca28c5abc2b961071ac01c9a4cb14..8c12a9465e4098629c4a1afd215439e31a481ef8 100644
--- a/src/plugins/server/data.mli
+++ b/src/plugins/server/data.mli
@@ -181,10 +181,16 @@ end
 module Dictionary(E : Enum) : S_collection with type t = E.t
 
 (* -------------------------------------------------------------------------- *)
-(** {2 Misc} *)
+(** {2 Error handling} *)
 (* -------------------------------------------------------------------------- *)
 
-val failure : json -> ('a, Format.formatter, unit, 'b) format4 -> 'a
-(** @raise Yojson.Basic.Util.Type_error with provided message *)
+(** Exception thrown during the decoding of a request's inputs *)
+exception InputError of string
+
+val failure : ?json:json -> ('a, Format.formatter, unit, 'b) format4 -> 'a
+(** @raise InputError with provided message *)
+
+val failure_from_type_error : string -> json -> 'a
+(** @raise InputError from Yojson.Basic.Util.Type_error arguments *)
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml
index 229c526ab6f75a73624235f3c09c42b5a4ed27e5..77605bf53f37fa4b3c2518de252644bcaa148c17 100644
--- a/src/plugins/server/kernel_ast.ml
+++ b/src/plugins/server/kernel_ast.ml
@@ -107,13 +107,14 @@ module Stmt = Data.Collection
           ~descr:(Md.rm "Code statement identifier") ()
       let to_json st = `String (Tag.of_stmt st)
       let of_json js =
+        let id = Js.to_string js in
         try
           let open Printer_tag in
-          match Tag.lookup (Js.to_string js) with
+          match Tag.lookup id with
           | PStmt(_,st) -> st
           | _ -> raise Not_found
         with Not_found ->
-          Data.failure js "Unknown stmt id"
+          Data.failure "Unknown stmt id: '%s'" id
     end)
 
 module Ki = Data.Collection
@@ -137,8 +138,9 @@ module Kf = Data.Collection
       let to_json kf =
         `String (Kernel_function.get_name kf)
       let of_json js =
-        try Js.to_string js |> Globals.Functions.find_by_name
-        with Not_found -> Data.failure js "Undefined function"
+        let key = Js.to_string js in
+        try Globals.Functions.find_by_name key
+        with Not_found -> Data.failure "Undefined function '%s'" key
     end)
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/server/kernel_main.ml b/src/plugins/server/kernel_main.ml
index 4cfd33596d14017a5ea0e0584435616387d44b84..7448c53e42df57194b8c9855689822507fb1e25a 100644
--- a/src/plugins/server/kernel_main.ml
+++ b/src/plugins/server/kernel_main.ml
@@ -78,7 +78,7 @@ struct
     | `Assoc [ "file" , `String path ; "line" , `Int line ]
     | `Assoc [ "line" , `Int line ; "file" , `String path ]
       -> Log.source ~file:(Filepath.Normalized.of_string path) ~line
-    | js -> failure js "Invalid source format"
+    | js -> failure_from_type_error "Invalid source format" js
 
 end
 
diff --git a/src/plugins/server/main.ml b/src/plugins/server/main.ml
index 2602e89fe5f4b7cef908529ccf56db56f41dc3ad..c00a228cf41eeb502c18f4eb23bf1695d5deb581 100644
--- a/src/plugins/server/main.ml
+++ b/src/plugins/server/main.ml
@@ -134,24 +134,28 @@ let pp_response pp fmt (r : _ response) =
 
 let no_yield () = ()
 
-let execute yield exec : _ response =
-  let db = !Db.progress in
+let execute exec : _ response =
   try
-    Db.progress := if exec.yield then yield else no_yield ;
     let data = exec.handler exec.data in
-    Db.progress := db ; `Data(exec.id,data)
+    `Data(exec.id,data)
   with
-  | Killed -> Db.progress := db ; `Killed exec.id
-  | exn ->
-    Db.progress := db ;
+  | Killed -> `Killed exec.id
+  | Data.InputError msg -> `Error(exec.id,msg)
+  | Sys.Break as exn -> raise exn (* Silently pass the exception *)
+  | exn when Cmdline.catch_at_toplevel exn ->
     Senv.warning "[%s] Uncaught exception:@\n%s"
       exec.request (Cmdline.protect exn) ;
     `Error(exec.id,Printexc.to_string exn)
 
+let execute_with_yield yield exec =
+  let db = !Db.progress in
+  Db.progress := if exec.yield then yield else no_yield ;
+  Extlib.try_finally ~finally:(fun () -> Db.progress := db) execute exec
+
 let execute_debug pp yield exec =
   if Senv.debug_atleast 1 then
     Senv.debug "Trigger %s:%a" exec.request pp exec.id ;
-  execute yield exec
+  execute_with_yield yield exec
 
 let reply_debug server resp =
   if Senv.debug_atleast 1 then
@@ -191,7 +195,7 @@ let process_request (server : 'a server) (request : 'a request) : unit =
       | Some( `GET , handler ) ->
         let exec = { id ; request ; handler ; data ;
                      yield = false ; killed = false } in
-        reply_debug server (execute no_yield exec)
+        reply_debug server (execute exec)
       | Some( `SET , handler ) ->
         let exec = { id ; request ; handler ; data ;
                      yield = false ; killed = false } in
@@ -283,18 +287,24 @@ let run ~pretty ?(equal=(=)) ~fetch () =
       shutdown = false ;
     } in
     try
+      (* TODO: remove the following line once the Why3 signal handler is not
+         used anymore. *)
+      Sys.catch_break true;
       signal true ;
       Senv.feedback "Server running." ;
-      while not server.shutdown do
-        let activity = process server in
-        if not activity then Unix.sleepf idle_s ;
-      done ;
+      begin try
+          while not server.shutdown do
+            let activity = process server in
+            if not activity then Unix.sleepf idle_s ;
+          done ;
+        with Sys.Break -> () (* Ctr+C, just leave the loop normally *)
+      end;
       Senv.feedback "Server shutdown." ;
       signal false ;
-    with err ->
+    with exn ->
       Senv.feedback "Server interruped (fatal error)." ;
       signal false ;
-      raise err
+      raise exn
   end
 
 (* -------------------------------------------------------------------------- *)
diff --git a/src/plugins/server/request.ml b/src/plugins/server/request.ml
index b355b3907879b1e91eef4345b217d39680fb98bc..039ee9f3c3c161cc5fb5d7f9fa688b1f50b625ec 100644
--- a/src/plugins/server/request.ml
+++ b/src/plugins/server/request.ml
@@ -175,7 +175,7 @@ type ('a,'b) signature = {
 }
 
 let failure_missing fmap name =
-  Data.failure (fmap_to_json fmap) "Missing parameter '%s'" name
+  Data.failure ~json:(fmap_to_json fmap) "Missing parameter '%s'" name
 
 let check_required fmap fd =
   if not (Fmap.mem fd fmap) then failure_missing fmap fd
@@ -276,9 +276,16 @@ let mk_input (type a) name defaults (input : a rq_input) : (rq -> json -> a) =
   | Pnone -> Senv.fatal "No input defined for request '%s'" name
   | Pdata d ->
     let module D = (val d) in
-    (fun rq js -> rq.result <- defaults ; D.of_json js)
+    begin fun rq js ->
+      rq.result <- defaults ;
+      try D.of_json js
+      with Jutil.Type_error (msg, js) -> Data.failure_from_type_error msg js
+    end
   | Pfields _ ->
-    (fun rq js -> rq.param <- fmap_of_json rq.param js)
+    begin fun rq js ->
+      try rq.param <- fmap_of_json rq.param js
+      with Jutil.Type_error (msg, js) -> Data.failure_from_type_error msg js
+    end
 
 (* json output processing *)
 let mk_output (type b) name required (output : b rq_output) : (rq -> b -> json) =