         input-var-names    (set (map key vars))
         missing-var-names  (set/difference required-var-names input-var-names)
         variables (merge default-vars vars)]
-    [(map (fn erorr-msg [name] {:message (format "Missing input variables (%s)." name)}) missing-var-names)
-     variables]))
+    {:errors (map (fn erorr-msg [name] {:message (format "Missing input variables (%s)." name)}) missing-var-names)
+     :variables variables}))
 
 (defn- execute-statement [{:keys [tag selection-set variable-definitions] :as statement} {:keys [variables schema] :as state}]
   (assert schema "Schema is nil in state!")
-  (let [[var-errors updated-variables] (guard-missing-vars variable-definitions variables)
+  (let [validated-variables (guard-missing-vars variable-definitions variables)
+        var-errors (:errors validated-variables)
+        updated-variables (:variables validated-variables)
         root-type (case tag
                     :query-definition (get-in schema [:roots :query])
                     :selection-set (get-in schema [:roots :query]) ; anonymous default query

    (assert root-type "No root type found in schema.")
    (if (seq var-errors)
      [var-errors nil]
      (execute-fields selection-set (assoc state :variables updated-variables) root-type :root))))

(defn- execute-document
  [document state]

  ;; executed. Current implementation will merge result from multiple
  ;; statements.
  (let [results (map #(execute-statement % state) document)
        {:keys [errors vals]} (rollup-errors results)]
    (if (seq errors)
      {:errors errors}
      {:data (into {} vals)})))

;; Public API

