diff --git a/console/console.go b/console/console.go
index 37c9f0afad2449507df4a60a74dcdc2e50578693..d10353093f2ef4410c67cc3f36f8d5db196a79b2 100644
--- a/console/console.go
+++ b/console/console.go
@@ -182,7 +182,11 @@ func (c *Console) init(preload []string) error {
 	// Preload any JavaScript files before starting the console
 	for _, path := range preload {
 		if err := c.jsre.Exec(path); err != nil {
-			return fmt.Errorf("%s: %v", path, jsErrorString(err))
+			failure := err.Error()
+			if ottoErr, ok := err.(*otto.Error); ok {
+				failure = ottoErr.String()
+			}
+			return fmt.Errorf("%s: %v", path, failure)
 		}
 	}
 	// Configure the console's input prompter for scrollback and tab completion
@@ -269,7 +273,6 @@ func (c *Console) Evaluate(statement string) error {
 		}
 	}()
 	if err := c.jsre.Evaluate(statement, c.printer); err != nil {
-		fmt.Fprintf(c.printer, "%v\n", jsErrorString(err))
 		return err
 	}
 	return nil
@@ -359,11 +362,3 @@ func (c *Console) Stop(graceful bool) error {
 	c.jsre.Stop(graceful)
 	return nil
 }
-
-// jsErrorString adds a backtrace to errors generated by otto.
-func jsErrorString(err error) string {
-	if ottoErr, ok := err.(*otto.Error); ok {
-		return ottoErr.String()
-	}
-	return err.Error()
-}
diff --git a/console/console_test.go b/console/console_test.go
index 5d38331e8ccb540801d38e323eed9905bacbefca..72d3a2df691214156568794c49e629322fb4c580 100644
--- a/console/console_test.go
+++ b/console/console_test.go
@@ -281,3 +281,15 @@ func TestPrettyPrint(t *testing.T) {
 		t.Fatalf("pretty print mismatch: have %s, want %s", output, want)
 	}
 }
+
+// Tests that the JavaScript exceptions are properly formatted and colored.
+func TestPrettyError(t *testing.T) {
+	tester := newTester(t, nil)
+	defer tester.Close(t)
+	tester.console.Evaluate("throw 'hello'")
+
+	want := jsre.ErrorColor("hello") + "\n"
+	if output := string(tester.output.Bytes()); output != want {
+		t.Fatalf("pretty error mismatch: have %s, want %s", output, want)
+	}
+}
diff --git a/internal/jsre/jsre.go b/internal/jsre/jsre.go
index 8d8f4fc2a93587f5b48d748b02f4f221c9e8d2ed..a95efd379dbcf312f6aa5c7ed21df9fba8165857 100644
--- a/internal/jsre/jsre.go
+++ b/internal/jsre/jsre.go
@@ -303,11 +303,11 @@ func (self *JSRE) Evaluate(code string, w io.Writer) error {
 	self.Do(func(vm *otto.Otto) {
 		val, err := vm.Run(code)
 		if err != nil {
-			fail = err
+			prettyError(vm, err, w)
 		} else {
 			prettyPrint(vm, val, w)
-			fmt.Fprintln(w)
 		}
+		fmt.Fprintln(w)
 	})
 	return fail
 }
diff --git a/internal/jsre/pretty.go b/internal/jsre/pretty.go
index cf4bf2cf89ebb4cca58e0a501c01700cdd5ffb7c..30d8660ff6ec2aca127d4bb26c6e866a3fa1707d 100644
--- a/internal/jsre/pretty.go
+++ b/internal/jsre/pretty.go
@@ -37,6 +37,7 @@ var (
 	SpecialColor  = color.New(color.Bold).SprintfFunc()
 	NumberColor   = color.New(color.FgRed).SprintfFunc()
 	StringColor   = color.New(color.FgGreen).SprintfFunc()
+	ErrorColor    = color.New(color.FgHiRed).SprintfFunc()
 )
 
 // these fields are hidden when printing objects.
@@ -55,6 +56,23 @@ func prettyPrint(vm *otto.Otto, value otto.Value, w io.Writer) {
 	ppctx{vm: vm, w: w}.printValue(value, 0, false)
 }
 
+// prettyError writes err to standard output.
+func prettyError(vm *otto.Otto, err error, w io.Writer) {
+	failure := err.Error()
+	if ottoErr, ok := err.(*otto.Error); ok {
+		failure = ottoErr.String()
+	}
+	fmt.Fprint(w, ErrorColor("%s", failure))
+}
+
+// jsErrorString adds a backtrace to errors generated by otto.
+func jsErrorString(err error) string {
+	if ottoErr, ok := err.(*otto.Error); ok {
+		return ottoErr.String()
+	}
+	return err.Error()
+}
+
 func prettyPrintJS(call otto.FunctionCall, w io.Writer) otto.Value {
 	for _, v := range call.ArgumentList {
 		prettyPrint(call.Otto, v, w)