diff --git a/python_payload/st3m/application.py b/python_payload/st3m/application.py
index 6d213c1a5e5c60de5a0bd8cae726dec8c069299f..24e622245a4454f9b107608d6188d14c8a0590bc 100644
--- a/python_payload/st3m/application.py
+++ b/python_payload/st3m/application.py
@@ -15,12 +15,14 @@ from st3m.ui import led_patterns
 import leds
 
 import toml
+import io
 import os
 import os.path
 import stat
 import sys
 import sys_display
 import random
+import time
 from math import sin
 
 log = Log(__name__)
@@ -69,11 +71,12 @@ class Application(BaseView):
 class BundleLoadException(BaseException):
     MSG = "failed to load"
 
-    def __init__(self, msg: Optional[str] = None) -> None:
+    def __init__(self, msg: Optional[str] = None, orig_exc: Optional[Exception] = None) -> None:
         res = self.MSG
         if msg is not None:
             res += ": " + msg
         self.msg = res
+        self.orig_exc = orig_exc
         super().__init__(res)
 
 
@@ -201,7 +204,7 @@ class BundleMetadata:
             return inst  # type: ignore
         except Exception as e:
             self._sys_path_set(old_sys_path)
-            raise BundleLoadException(f"load error: {e}")
+            raise BundleLoadException(f"load error: {e}", e)
 
     def load(self) -> Application:
         """
@@ -245,11 +248,34 @@ class BundleMetadata:
 
 
 class LoadErrorView(BaseView):
-    def __init__(self, e: BundleLoadException) -> None:
+    def __init__(self, e: BaseException) -> None:
         super().__init__()
         self.e = e
         self.header = "oh no"
 
+        self.lines: List[List[str]] = []
+
+        stringio = io.StringIO()
+        sys.print_exception(self.e, stringio)
+        msg = stringio.getvalue()
+
+        for line in msg.split("\n"):
+            for word in line.split():
+                if len(self.lines) == 0:
+                    self.lines.append([word])
+                    continue
+                lastline = self.lines[-1][:]
+                lastline.append(word)
+                if sum(len(l) for l in lastline) + len(lastline) - 1 > 35:
+                    self.lines.append([word])
+                else:
+                    self.lines[-1].append(word)
+            self.lines.append([])
+
+        self.scroll_pos = 0
+        self.max_lines = 9
+        self.scroll_max = len(self.lines) - self.max_lines
+
     def on_enter(self, vm: Optional[ViewManager]) -> None:
         self.header = random.choice(
             [
@@ -262,7 +288,14 @@ class LoadErrorView(BaseView):
         )
 
     def think(self, ins: InputState, delta_ms: int) -> None:
-        pass
+        super().think(ins, delta_ms)
+
+        direction = ins.buttons.app
+
+        if direction == ins.buttons.PRESSED_LEFT or ins.captouch.petals[0].pressed:
+            self.scroll_pos = max(0, self.scroll_pos - delta_ms/100)
+        elif direction == ins.buttons.PRESSED_RIGHT or ins.captouch.petals[5].pressed:
+            self.scroll_pos = min(self.scroll_max, self.scroll_pos + delta_ms/100)
 
     def draw(self, ctx: Context) -> None:
         ctx.rgb(0.8, 0.1, 0.1)
@@ -276,19 +309,6 @@ class LoadErrorView(BaseView):
         ctx.move_to(0, -70)
         ctx.text(self.header)
 
-        lines: List[List[str]] = []
-        msg = self.e.msg
-        for word in msg.split():
-            if len(lines) == 0:
-                lines.append([word])
-                continue
-            lastline = lines[-1][:]
-            lastline.append(word)
-            if sum(len(l) for l in lastline) + len(lastline) - 1 > 30:
-                lines.append([word])
-            else:
-                lines[-1].append(word)
-
         ctx.gray(0)
         ctx.rectangle(-120, -60, 240, 240).fill()
         y = -40
@@ -296,11 +316,33 @@ class LoadErrorView(BaseView):
         ctx.font_size = 15
         ctx.font = "Arimo Regular"
         ctx.text_align = ctx.LEFT
-        for line in lines:
-            ctx.move_to(-90, y)
+
+        view_start = max(0, int(self.scroll_pos))
+        view_end = min(len(self.lines), view_start + self.max_lines)
+        print(view_start, view_end, self.scroll_pos)
+
+        for line in self.lines[view_start : view_end]:
+            ctx.move_to(-100, y)
             ctx.text(" ".join(line))
             y += 15
 
+        ctx.font = "Material Icons"
+        ctx.text_align = ctx.CENTER
+
+        animation = ((time.ticks_ms() / 69) % 20) - 10
+        if animation < 10:
+            animation = -animation
+        animation *= animation / 10
+        animation = 10 - animation
+
+        if view_end < len(self.lines):
+            ctx.move_to(0, 120 - animation/2)
+            ctx.text("\ue5db")
+
+        if view_start > 0:
+            ctx.move_to(0, -105 + animation/2)
+            ctx.text("\ue5d8")
+
 
 class MenuItemAppLaunch(MenuItem):
     """
@@ -325,6 +367,8 @@ class MenuItemAppLaunch(MenuItem):
                 self._instance = self._bundle.load()
             except BundleLoadException as e:
                 log.error(f"Could not load {self.label()}: {e}")
+                if getattr(e, 'orig_exc'):
+                    e = e.orig_exc
                 sys.print_exception(e)
                 err = LoadErrorView(e)
                 vm.push(err)