about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-01-02 21:39:15 -0600
committerPaul Frazee <pfrazee@gmail.com>2023-01-02 21:39:15 -0600
commit4eabc2d65aa742e6cf55822943f04275531d0375 (patch)
tree645742da4a45eef45019d2d0193f022b3672e01c /src
parent6885fb2b41efdb29e386cf696ea7304baf3a87c8 (diff)
downloadvoidsky-4eabc2d65aa742e6cf55822943f04275531d0375.tar.zst
Improve error logging
Diffstat (limited to 'src')
-rw-r--r--src/state/index.ts4
-rw-r--r--src/state/lib/api.ts5
-rw-r--r--src/state/models/feed-view.ts15
-rw-r--r--src/state/models/get-assertions-view.ts9
-rw-r--r--src/state/models/log.ts39
-rw-r--r--src/state/models/me.ts15
-rw-r--r--src/state/models/members-view.ts9
-rw-r--r--src/state/models/memberships-view.ts9
-rw-r--r--src/state/models/notifications-view.ts21
-rw-r--r--src/state/models/post-thread-view.ts5
-rw-r--r--src/state/models/post.ts8
-rw-r--r--src/state/models/profile-ui.ts16
-rw-r--r--src/state/models/profile-view.ts9
-rw-r--r--src/state/models/reposted-by-view.ts9
-rw-r--r--src/state/models/root-store.ts2
-rw-r--r--src/state/models/session.ts17
-rw-r--r--src/state/models/suggested-actors-view.ts9
-rw-r--r--src/state/models/suggested-invites-view.ts11
-rw-r--r--src/state/models/user-followers-view.ts7
-rw-r--r--src/state/models/user-follows-view.ts7
-rw-r--r--src/state/models/votes-view.ts9
-rw-r--r--src/view/com/composer/PhotoCarouselPicker.tsx4
-rw-r--r--src/view/com/discover/SuggestedFollows.tsx8
-rw-r--r--src/view/com/login/CreateAccount.tsx4
-rw-r--r--src/view/com/login/Signin.tsx8
-rw-r--r--src/view/com/modals/CreateScene.tsx12
-rw-r--r--src/view/com/modals/InviteToScene.tsx6
-rw-r--r--src/view/com/notifications/Feed.tsx10
-rw-r--r--src/view/com/post-thread/PostRepostedBy.tsx4
-rw-r--r--src/view/com/post-thread/PostThread.tsx5
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx6
-rw-r--r--src/view/com/post-thread/PostVotedBy.tsx2
-rw-r--r--src/view/com/post/Post.tsx10
-rw-r--r--src/view/com/post/PostText.tsx4
-rw-r--r--src/view/com/posts/Feed.tsx9
-rw-r--r--src/view/com/posts/FeedItem.tsx6
-rw-r--r--src/view/com/profile/ProfileFollowers.tsx4
-rw-r--r--src/view/com/profile/ProfileFollows.tsx4
-rw-r--r--src/view/com/profile/ProfileHeader.tsx6
-rw-r--r--src/view/com/profile/ProfileMembers.tsx2
-rw-r--r--src/view/lib/ThemeContext.tsx1
-rw-r--r--src/view/lib/themes.ts5
-rw-r--r--src/view/screens/Home.tsx2
-rw-r--r--src/view/screens/Log.tsx10
-rw-r--r--src/view/screens/Notifications.tsx2
-rw-r--r--src/view/screens/PostThread.tsx2
-rw-r--r--src/view/screens/Profile.tsx7
47 files changed, 191 insertions, 187 deletions
diff --git a/src/state/index.ts b/src/state/index.ts
index a8b95cc65..bc8a16949 100644
--- a/src/state/index.ts
+++ b/src/state/index.ts
@@ -25,7 +25,7 @@ export async function setupState() {
     data = (await storage.load(ROOT_STATE_STORAGE_KEY)) || {}
     rootStore.hydrate(data)
   } catch (e: any) {
-    rootStore.log.error('Failed to load state from storage', e.toString())
+    rootStore.log.error('Failed to load state from storage', e)
   }
 
   rootStore.log.debug('Initial hydrate')
@@ -36,7 +36,7 @@ export async function setupState() {
       return rootStore.fetchStateUpdate()
     })
     .catch((e: any) => {
-      rootStore.log.warn('Failed initial connect', e.toString())
+      rootStore.log.warn('Failed initial connect', e)
     })
   // @ts-ignore .on() is correct -prf
   api.sessionManager.on('session', () => {
diff --git a/src/state/lib/api.ts b/src/state/lib/api.ts
index 6bbc43271..e701ae6f5 100644
--- a/src/state/lib/api.ts
+++ b/src/state/lib/api.ts
@@ -126,10 +126,7 @@ export async function post(
           },
         } as AppBskyEmbedExternal.Main
       } catch (e: any) {
-        store.log.warn(
-          `Failed to fetch link meta for ${link.value}`,
-          e.toString(),
-        )
+        store.log.warn(`Failed to fetch link meta for ${link.value}`, e)
       }
     }
   }
diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts
index c8827b1fb..28f1d77a3 100644
--- a/src/state/models/feed-view.ts
+++ b/src/state/models/feed-view.ts
@@ -320,11 +320,14 @@ export class FeedModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = cleanError(err)
+    this.error = err ? cleanError(err.toString()) : ''
+    if (err) {
+      this.rootStore.log.error('Posts feed request failed', err)
+    }
   }
 
   // loader functions
@@ -352,7 +355,7 @@ export class FeedModel {
       await this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(e.toString())
+      this._xIdle(e)
     }
   }
 
@@ -363,7 +366,7 @@ export class FeedModel {
       await this._prependAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(e.toString())
+      this._xIdle(e)
     }
   }
 
@@ -380,7 +383,7 @@ export class FeedModel {
       await this._appendAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load feed: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
@@ -408,7 +411,7 @@ export class FeedModel {
       } while (numToFetch > 0)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to update feed: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/get-assertions-view.ts b/src/state/models/get-assertions-view.ts
index 4778ef132..bdb2c0894 100644
--- a/src/state/models/get-assertions-view.ts
+++ b/src/state/models/get-assertions-view.ts
@@ -80,11 +80,14 @@ export class GetAssertionsView {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch assertions', err)
+    }
   }
 
   // loader functions
@@ -99,7 +102,7 @@ export class GetAssertionsView {
       this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(e.toString())
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/log.ts b/src/state/models/log.ts
index 42172a3b1..67f4a210c 100644
--- a/src/state/models/log.ts
+++ b/src/state/models/log.ts
@@ -1,4 +1,5 @@
 import {makeAutoObservable} from 'mobx'
+import {XRPCError, XRPCInvalidResponseError} from '@atproto/xrpc'
 import {isObj, hasProp} from '../lib/type-guards'
 
 interface LogEntry {
@@ -51,9 +52,7 @@ export class LogModel {
   }
 
   debug(summary: string, details?: any) {
-    if (details && typeof details !== 'string') {
-      details = JSON.stringify(details, null, 2)
-    }
+    details = detailsToStr(details)
     console.debug(summary, details || '')
     this.add({
       id: genId(),
@@ -65,10 +64,8 @@ export class LogModel {
   }
 
   warn(summary: string, details?: any) {
-    if (details && typeof details !== 'string') {
-      details = JSON.stringify(details, null, 2)
-    }
-    console.warn(summary, details || '')
+    details = detailsToStr(details)
+    console.debug(summary, details || '')
     this.add({
       id: genId(),
       type: 'warn',
@@ -79,10 +76,8 @@ export class LogModel {
   }
 
   error(summary: string, details?: any) {
-    if (details && typeof details !== 'string') {
-      details = JSON.stringify(details, null, 2)
-    }
-    console.error(summary, details || '')
+    details = detailsToStr(details)
+    console.debug(summary, details || '')
     this.add({
       id: genId(),
       type: 'error',
@@ -92,3 +87,25 @@ export class LogModel {
     })
   }
 }
+
+function detailsToStr(details?: any) {
+  if (details && typeof details !== 'string') {
+    if (
+      details instanceof XRPCInvalidResponseError ||
+      details.constructor.name === 'XRPCInvalidResponseError'
+    ) {
+      return `The server gave an ill-formatted response.\nMethod: ${
+        details.lexiconNsid
+      }.\nError: ${details.validationError.toString()}`
+    } else if (
+      details instanceof XRPCError ||
+      details.constructor.name === 'XRPCError'
+    ) {
+      return `An XRPC error occurred.\nStatus: ${details.status}\nError: ${details.error}\nMessage: ${details.message}`
+    } else if (details instanceof Error) {
+      return details.toString()
+    }
+    return JSON.stringify(details, null, 2)
+  }
+  return details
+}
diff --git a/src/state/models/me.ts b/src/state/models/me.ts
index ae1e6aed2..0ae52db8f 100644
--- a/src/state/models/me.ts
+++ b/src/state/models/me.ts
@@ -104,22 +104,13 @@ export class MeModel {
       })
       await Promise.all([
         this.memberships?.setup().catch(e => {
-          this.rootStore.log.error(
-            'Failed to setup memberships model',
-            e.toString(),
-          )
+          this.rootStore.log.error('Failed to setup memberships model', e)
         }),
         this.mainFeed.setup().catch(e => {
-          this.rootStore.log.error(
-            'Failed to setup main feed model',
-            e.toString(),
-          )
+          this.rootStore.log.error('Failed to setup main feed model', e)
         }),
         this.notifications.setup().catch(e => {
-          this.rootStore.log.error(
-            'Failed to setup notifications model',
-            e.toString(),
-          )
+          this.rootStore.log.error('Failed to setup notifications model', e)
         }),
       ])
     } else {
diff --git a/src/state/models/members-view.ts b/src/state/models/members-view.ts
index 35eafb583..73295f479 100644
--- a/src/state/models/members-view.ts
+++ b/src/state/models/members-view.ts
@@ -104,11 +104,14 @@ export class MembersViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch members', err)
+    }
   }
 
   // loader functions
@@ -123,7 +126,7 @@ export class MembersViewModel {
       this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load feed: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/memberships-view.ts b/src/state/models/memberships-view.ts
index 99bb25645..661b3f6ae 100644
--- a/src/state/models/memberships-view.ts
+++ b/src/state/models/memberships-view.ts
@@ -82,11 +82,14 @@ export class MembershipsViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch memberships', err)
+    }
   }
 
   // loader functions
@@ -101,7 +104,7 @@ export class MembershipsViewModel {
       this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load feed: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts
index 38a8ca133..44f92dd2f 100644
--- a/src/state/models/notifications-view.ts
+++ b/src/state/models/notifications-view.ts
@@ -151,7 +151,7 @@ export class NotificationsViewItemModel implements GroupedNotification {
       await this.additionalPost.setup().catch(e => {
         this.rootStore.log.error(
           'Failed to load post needed by notification',
-          e.toString(),
+          e,
         )
       })
     }
@@ -266,10 +266,7 @@ export class NotificationsViewModel {
       })
       this.rootStore.me.clearNotificationCount()
     } catch (e: any) {
-      this.rootStore.log.warn(
-        'Failed to update notifications read state',
-        e.toString(),
-      )
+      this.rootStore.log.warn('Failed to update notifications read state', e)
     }
   }
 
@@ -282,11 +279,15 @@ export class NotificationsViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
     this.error = cleanError(err)
+    this.error = err ? cleanError(err) : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch notifications', err)
+    }
   }
 
   // loader functions
@@ -314,7 +315,7 @@ export class NotificationsViewModel {
       await this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load notifications: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
@@ -332,7 +333,7 @@ export class NotificationsViewModel {
       await this._appendAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load notifications: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
@@ -359,7 +360,7 @@ export class NotificationsViewModel {
       } while (numToFetch > 0)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to update notifications: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
@@ -386,7 +387,7 @@ export class NotificationsViewModel {
     await Promise.all(promises).catch(e => {
       this.rootStore.log.error(
         'Uncaught failure during notifications-view _appendAll()',
-        e.toString(),
+        e,
       )
     })
     runInAction(() => {
diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts
index 2ada18a40..b7c33cfbd 100644
--- a/src/state/models/post-thread-view.ts
+++ b/src/state/models/post-thread-view.ts
@@ -236,11 +236,14 @@ export class PostThreadViewModel {
     this.notFound = false
   }
 
-  private _xIdle(err: any = undefined) {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
     this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch assertions', err)
+    }
     this.notFound = err instanceof GetPostThread.NotFoundError
   }
 
diff --git a/src/state/models/post.ts b/src/state/models/post.ts
index 1c49e32f2..497c8e4c9 100644
--- a/src/state/models/post.ts
+++ b/src/state/models/post.ts
@@ -63,10 +63,14 @@ export class PostModel implements RemoveIndex<Post.Record> {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.hasLoaded = true
     this.error = cleanError(err)
+    this.error = err ? cleanError(err) : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch post', err)
+    }
   }
 
   // loader functions
@@ -87,7 +91,7 @@ export class PostModel implements RemoveIndex<Post.Record> {
       this._replaceAll(res.value)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(e.toString())
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/profile-ui.ts b/src/state/models/profile-ui.ts
index 081160e65..fb90fb694 100644
--- a/src/state/models/profile-ui.ts
+++ b/src/state/models/profile-ui.ts
@@ -114,28 +114,20 @@ export class ProfileUiModel {
     await Promise.all([
       this.profile
         .setup()
-        .catch(err =>
-          this.rootStore.log.error('Failed to fetch profile', err.toString()),
-        ),
+        .catch(err => this.rootStore.log.error('Failed to fetch profile', err)),
       this.feed
         .setup()
-        .catch(err =>
-          this.rootStore.log.error('Failed to fetch feed', err.toString()),
-        ),
+        .catch(err => this.rootStore.log.error('Failed to fetch feed', err)),
     ])
     if (this.isUser) {
       await this.memberships
         .setup()
-        .catch(err =>
-          this.rootStore.log.error('Failed to fetch members', err.toString()),
-        )
+        .catch(err => this.rootStore.log.error('Failed to fetch members', err))
     }
     if (this.isScene) {
       await this.members
         .setup()
-        .catch(err =>
-          this.rootStore.log.error('Failed to fetch members', err.toString()),
-        )
+        .catch(err => this.rootStore.log.error('Failed to fetch members', err))
     }
   }
 
diff --git a/src/state/models/profile-view.ts b/src/state/models/profile-view.ts
index 1c825a482..2670627c3 100644
--- a/src/state/models/profile-view.ts
+++ b/src/state/models/profile-view.ts
@@ -178,11 +178,14 @@ export class ProfileViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch profile', err)
+    }
   }
 
   // loader functions
@@ -198,7 +201,7 @@ export class ProfileViewModel {
       this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(e.toString())
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/reposted-by-view.ts b/src/state/models/reposted-by-view.ts
index 624d86ec0..1ded30976 100644
--- a/src/state/models/reposted-by-view.ts
+++ b/src/state/models/reposted-by-view.ts
@@ -94,11 +94,14 @@ export class RepostedByViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch reposted by view', err)
+    }
   }
 
   // loader functions
@@ -127,7 +130,7 @@ export class RepostedByViewModel {
       this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load feed: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/root-store.ts b/src/state/models/root-store.ts
index 0166b67e6..5349f10d0 100644
--- a/src/state/models/root-store.ts
+++ b/src/state/models/root-store.ts
@@ -59,7 +59,7 @@ export class RootStoreModel {
       if (isNetworkError(e)) {
         this.session.setOnline(false) // connection lost
       }
-      this.log.error('Failed to fetch latest state', e.toString())
+      this.log.error('Failed to fetch latest state', e)
     }
   }
 
diff --git a/src/state/models/session.ts b/src/state/models/session.ts
index 3efb5d2a6..13e0fcbe0 100644
--- a/src/state/models/session.ts
+++ b/src/state/models/session.ts
@@ -124,7 +124,7 @@ export class SessionModel {
     } catch (e: any) {
       this.rootStore.log.error(
         `Invalid service URL: ${this.data.service}. Resetting session.`,
-        e.toString(),
+        e,
       )
       this.clear()
       return false
@@ -160,10 +160,7 @@ export class SessionModel {
           this.rootStore.me.clear()
         }
         this.rootStore.me.load().catch(e => {
-          this.rootStore.log.error(
-            'Failed to fetch local user information',
-            e.toString(),
-          )
+          this.rootStore.log.error('Failed to fetch local user information', e)
         })
         return // success
       }
@@ -207,10 +204,7 @@ export class SessionModel {
       this.configureApi()
       this.setOnline(true, false)
       this.rootStore.me.load().catch(e => {
-        this.rootStore.log.error(
-          'Failed to fetch local user information',
-          e.toString(),
-        )
+        this.rootStore.log.error('Failed to fetch local user information', e)
       })
     }
   }
@@ -246,10 +240,7 @@ export class SessionModel {
       this.rootStore.onboard.start()
       this.configureApi()
       this.rootStore.me.load().catch(e => {
-        this.rootStore.log.error(
-          'Failed to fetch local user information',
-          e.toString(),
-        )
+        this.rootStore.log.error('Failed to fetch local user information', e)
       })
     }
   }
diff --git a/src/state/models/suggested-actors-view.ts b/src/state/models/suggested-actors-view.ts
index f52830cfd..358a8491a 100644
--- a/src/state/models/suggested-actors-view.ts
+++ b/src/state/models/suggested-actors-view.ts
@@ -58,11 +58,14 @@ export class SuggestedActorsViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch suggested actors', err)
+    }
   }
 
   // loader functions
@@ -88,7 +91,7 @@ export class SuggestedActorsViewModel {
       )
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(e.toString())
+      this._xIdle(e)
     }
   }
 
diff --git a/src/state/models/suggested-invites-view.ts b/src/state/models/suggested-invites-view.ts
index eb0665bca..fadc956cc 100644
--- a/src/state/models/suggested-invites-view.ts
+++ b/src/state/models/suggested-invites-view.ts
@@ -83,11 +83,14 @@ export class SuggestedInvitesView {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch suggested invites', err)
+    }
   }
 
   // loader functions
@@ -101,7 +104,7 @@ export class SuggestedInvitesView {
     } catch (e: any) {
       this.rootStore.log.error(
         'Failed to fetch current scene members in suggested invites',
-        e.toString(),
+        e,
       )
       this._xIdle(
         'Failed to fetch the current scene members. Check your internet connection and try again.',
@@ -113,7 +116,7 @@ export class SuggestedInvitesView {
     } catch (e: any) {
       this.rootStore.log.error(
         'Failed to fetch current followers in suggested invites',
-        e.toString(),
+        e,
       )
       this._xIdle(
         'Failed to fetch the your current followers. Check your internet connection and try again.',
diff --git a/src/state/models/user-followers-view.ts b/src/state/models/user-followers-view.ts
index 2d8d7cf13..6cb8dfeb6 100644
--- a/src/state/models/user-followers-view.ts
+++ b/src/state/models/user-followers-view.ts
@@ -76,11 +76,14 @@ export class UserFollowersViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch user followers', err)
+    }
   }
 
   // loader functions
diff --git a/src/state/models/user-follows-view.ts b/src/state/models/user-follows-view.ts
index 8cbafddf9..341f0f806 100644
--- a/src/state/models/user-follows-view.ts
+++ b/src/state/models/user-follows-view.ts
@@ -76,11 +76,14 @@ export class UserFollowsViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch user follows', err)
+    }
   }
 
   // loader functions
diff --git a/src/state/models/votes-view.ts b/src/state/models/votes-view.ts
index c92d8ae22..937667b44 100644
--- a/src/state/models/votes-view.ts
+++ b/src/state/models/votes-view.ts
@@ -91,11 +91,14 @@ export class VotesViewModel {
     this.error = ''
   }
 
-  private _xIdle(err: string = '') {
+  private _xIdle(err?: any) {
     this.isLoading = false
     this.isRefreshing = false
     this.hasLoaded = true
-    this.error = err
+    this.error = err ? err.toString() : ''
+    if (err) {
+      this.rootStore.log.error('Failed to fetch votes', err)
+    }
   }
 
   // loader functions
@@ -124,7 +127,7 @@ export class VotesViewModel {
       this._replaceAll(res)
       this._xIdle()
     } catch (e: any) {
-      this._xIdle(`Failed to load feed: ${e.toString()}`)
+      this._xIdle(e)
     }
   }
 
diff --git a/src/view/com/composer/PhotoCarouselPicker.tsx b/src/view/com/composer/PhotoCarouselPicker.tsx
index f7a3d7987..ba04c5bc7 100644
--- a/src/view/com/composer/PhotoCarouselPicker.tsx
+++ b/src/view/com/composer/PhotoCarouselPicker.tsx
@@ -40,7 +40,7 @@ export const PhotoCarouselPicker = ({
       onSelectPhotos([uri, ...selectedPhotos])
     } catch (err: any) {
       // ignore
-      store.log.warn('Error using camera', err.toString())
+      store.log.warn('Error using camera', err)
     }
   }, [store.log, selectedPhotos, onSelectPhotos])
 
@@ -56,7 +56,7 @@ export const PhotoCarouselPicker = ({
         onSelectPhotos([finalUri, ...selectedPhotos])
       } catch (err: any) {
         // ignore
-        store.log.warn('Error selecting photo', err.toString())
+        store.log.warn('Error selecting photo', err)
       }
     },
     [store.log, selectedPhotos, onSelectPhotos],
diff --git a/src/view/com/discover/SuggestedFollows.tsx b/src/view/com/discover/SuggestedFollows.tsx
index 936dcd6db..017bd08c8 100644
--- a/src/view/com/discover/SuggestedFollows.tsx
+++ b/src/view/com/discover/SuggestedFollows.tsx
@@ -45,7 +45,7 @@ export const SuggestedFollows = observer(
       view
         .setup()
         .catch((err: any) =>
-          store.log.error('Failed to fetch suggestions', err.toString()),
+          store.log.error('Failed to fetch suggestions', err),
         )
     }, [view, store.log])
 
@@ -59,7 +59,7 @@ export const SuggestedFollows = observer(
       view
         .setup()
         .catch((err: any) =>
-          store.log.error('Failed to fetch suggestions', err.toString()),
+          store.log.error('Failed to fetch suggestions', err),
         )
 
     const onPressFollow = async (item: SuggestedActor) => {
@@ -67,7 +67,7 @@ export const SuggestedFollows = observer(
         const res = await apilib.follow(store, item.did, item.declaration.cid)
         setFollows({[item.did]: res.uri, ...follows})
       } catch (e: any) {
-        store.log.error('Failed fo create follow', {error: e.toString(), item})
+        store.log.error('Failed fo create follow', e)
         Toast.show('An issue occurred, please try again.')
       }
     }
@@ -76,7 +76,7 @@ export const SuggestedFollows = observer(
         await apilib.unfollow(store, follows[item.did])
         setFollows(_omit(follows, [item.did]))
       } catch (e: any) {
-        store.log.error('Failed fo delete follow', {error: e.toString(), item})
+        store.log.error('Failed fo delete follow', e)
         Toast.show('An issue occurred, please try again.')
       }
     }
diff --git a/src/view/com/login/CreateAccount.tsx b/src/view/com/login/CreateAccount.tsx
index f07ad7071..7f128d69a 100644
--- a/src/view/com/login/CreateAccount.tsx
+++ b/src/view/com/login/CreateAccount.tsx
@@ -54,7 +54,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => {
         if (aborted) return
         store.log.warn(
           `Failed to fetch service description for ${serviceUrl}`,
-          err.toString(),
+          err,
         )
         setError(
           'Unable to contact your service. Please check your Internet connection.',
@@ -100,7 +100,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => {
         errMsg =
           'Invite code not accepted. Check that you input it correctly and try again.'
       }
-      store.log.warn('Failed to create account', e.toString())
+      store.log.error('Failed to create account', e)
       setIsProcessing(false)
       setError(errMsg.replace(/^Error:/, ''))
     }
diff --git a/src/view/com/login/Signin.tsx b/src/view/com/login/Signin.tsx
index 0a78b6401..32c3633d3 100644
--- a/src/view/com/login/Signin.tsx
+++ b/src/view/com/login/Signin.tsx
@@ -53,7 +53,7 @@ export const Signin = ({onPressBack}: {onPressBack: () => void}) => {
         if (aborted) return
         store.log.warn(
           `Failed to fetch service description for ${serviceUrl}`,
-          err.toString(),
+          err,
         )
         setError(
           'Unable to contact your service. Please check your Internet connection.',
@@ -171,7 +171,7 @@ const LoginForm = ({
       })
     } catch (e: any) {
       const errMsg = e.toString()
-      store.log.warn('Failed to login', e.toString())
+      store.log.warn('Failed to login', e)
       setIsProcessing(false)
       if (errMsg.includes('Authentication Required')) {
         setError('Invalid username or password')
@@ -307,7 +307,7 @@ const ForgotPasswordForm = ({
       onEmailSent()
     } catch (e: any) {
       const errMsg = e.toString()
-      store.log.warn('Failed to request password reset', e.toString())
+      store.log.warn('Failed to request password reset', e)
       setIsProcessing(false)
       if (isNetworkError(e)) {
         setError(
@@ -419,7 +419,7 @@ const SetNewPasswordForm = ({
       onPasswordSet()
     } catch (e: any) {
       const errMsg = e.toString()
-      store.log.warn('Failed to set new password', e.toString())
+      store.log.warn('Failed to set new password', e)
       setIsProcessing(false)
       if (isNetworkError(e)) {
         setError(
diff --git a/src/view/com/modals/CreateScene.tsx b/src/view/com/modals/CreateScene.tsx
index c26087850..d92fe2e31 100644
--- a/src/view/com/modals/CreateScene.tsx
+++ b/src/view/com/modals/CreateScene.tsx
@@ -57,10 +57,7 @@ export function Component({}: {}) {
         })
         .catch(e =>
           // an error here is not critical
-          store.log.error(
-            'Failed to update scene profile during creation',
-            e.toString(),
-          ),
+          store.log.error('Failed to update scene profile during creation', e),
         )
       // follow the scene
       await store.api.app.bsky.graph.follow
@@ -78,10 +75,7 @@ export function Component({}: {}) {
         )
         .catch(e =>
           // an error here is not critical
-          store.log.error(
-            'Failed to follow scene after creation',
-            e.toString(),
-          ),
+          store.log.error('Failed to follow scene after creation', e),
         )
       Toast.show('Scene created')
       store.shell.closeModal()
@@ -94,7 +88,7 @@ export function Component({}: {}) {
       } else if (e instanceof AppBskyActorCreateScene.HandleNotAvailableError) {
         setError(`The handle "${handle}" is not available.`)
       } else {
-        store.log.error('Failed to create scene', e.toString())
+        store.log.error('Failed to create scene', e)
         setError(
           'Failed to create the scene. Check your internet connection and try again.',
         )
diff --git a/src/view/com/modals/InviteToScene.tsx b/src/view/com/modals/InviteToScene.tsx
index 6fe17b4dc..2b4d0ac29 100644
--- a/src/view/com/modals/InviteToScene.tsx
+++ b/src/view/com/modals/InviteToScene.tsx
@@ -86,7 +86,7 @@ export const Component = observer(function Component({
       Toast.show('Invite sent')
     } catch (e: any) {
       setError('There was an issue with the invite. Please try again.')
-      store.log.error('Failed to invite user to scene', e.toString())
+      store.log.error('Failed to invite user to scene', e)
     }
   }
   const onPressUndo = async (subjectDid: string, assertionUri: string) => {
@@ -100,7 +100,7 @@ export const Component = observer(function Component({
       setCreatedInvites(_omit(createdInvites, [subjectDid]))
     } catch (e: any) {
       setError('There was an issue with the invite. Please try again.')
-      store.log.error('Failed to delete a scene invite', e.toString())
+      store.log.error('Failed to delete a scene invite', e)
     }
   }
 
@@ -119,7 +119,7 @@ export const Component = observer(function Component({
       Toast.show('Invite removed')
     } catch (e: any) {
       setError('There was an issue with the invite. Please try again.')
-      store.log.error('Failed to delete an invite', e.toString())
+      store.log.error('Failed to delete an invite', e)
     }
   }
 
diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx
index 6406a598b..59b83bbab 100644
--- a/src/view/com/notifications/Feed.tsx
+++ b/src/view/com/notifications/Feed.tsx
@@ -39,20 +39,14 @@ export const Feed = observer(function Feed({
     view
       .refresh()
       .catch(err =>
-        view.rootStore.log.error(
-          'Failed to refresh notifications feed',
-          err.toString(),
-        ),
+        view.rootStore.log.error('Failed to refresh notifications feed', err),
       )
   }
   const onEndReached = () => {
     view
       .loadMore()
       .catch(err =>
-        view.rootStore.log.error(
-          'Failed to load more notifications',
-          err.toString(),
-        ),
+        view.rootStore.log.error('Failed to load more notifications', err),
       )
   }
   let data
diff --git a/src/view/com/post-thread/PostRepostedBy.tsx b/src/view/com/post-thread/PostRepostedBy.tsx
index 4ca20aedd..5dbb6219e 100644
--- a/src/view/com/post-thread/PostRepostedBy.tsx
+++ b/src/view/com/post-thread/PostRepostedBy.tsx
@@ -28,9 +28,7 @@ export const PostRepostedBy = observer(function PostRepostedBy({
     setView(newView)
     newView
       .setup()
-      .catch(err =>
-        store.log.error('Failed to fetch reposted by', err.toString()),
-      )
+      .catch(err => store.log.error('Failed to fetch reposted by', err))
   }, [uri, view?.params.uri, store])
 
   const onRefresh = () => {
diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx
index 187fe6c11..dcdc1eb49 100644
--- a/src/view/com/post-thread/PostThread.tsx
+++ b/src/view/com/post-thread/PostThread.tsx
@@ -21,10 +21,7 @@ export const PostThread = observer(function PostThread({
     view
       ?.refresh()
       .catch(err =>
-        view.rootStore.log.error(
-          'Failed to refresh posts thread',
-          err.toString(),
-        ),
+        view.rootStore.log.error('Failed to refresh posts thread', err),
       )
   }
   const onLayout = () => {
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 456a6f465..e8c23d3a2 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -72,12 +72,12 @@ export const PostThreadItem = observer(function PostThreadItem({
   const onPressToggleRepost = () => {
     item
       .toggleRepost()
-      .catch(e => store.log.error('Failed to toggle repost', e.toString()))
+      .catch(e => store.log.error('Failed to toggle repost', e))
   }
   const onPressToggleUpvote = () => {
     item
       .toggleUpvote()
-      .catch(e => store.log.error('Failed to toggle upvote', e.toString()))
+      .catch(e => store.log.error('Failed to toggle upvote', e))
   }
   const onCopyPostText = () => {
     Clipboard.setString(record.text)
@@ -90,7 +90,7 @@ export const PostThreadItem = observer(function PostThreadItem({
         Toast.show('Post deleted')
       },
       e => {
-        store.log.error('Failed to delete post', e.toString())
+        store.log.error('Failed to delete post', e)
         Toast.show('Failed to delete post, please try again')
       },
     )
diff --git a/src/view/com/post-thread/PostVotedBy.tsx b/src/view/com/post-thread/PostVotedBy.tsx
index 21559e432..17ed9f9f8 100644
--- a/src/view/com/post-thread/PostVotedBy.tsx
+++ b/src/view/com/post-thread/PostVotedBy.tsx
@@ -30,7 +30,7 @@ export const PostVotedBy = observer(function PostVotedBy({
     setView(newView)
     newView
       .setup()
-      .catch(err => store.log.error('Failed to fetch voted by', err.toString()))
+      .catch(err => store.log.error('Failed to fetch voted by', err))
   }, [uri, view?.params.uri, store])
 
   const onRefresh = () => {
diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx
index d55027a94..351282df4 100644
--- a/src/view/com/post/Post.tsx
+++ b/src/view/com/post/Post.tsx
@@ -47,9 +47,7 @@ export const Post = observer(function Post({
     }
     const newView = new PostThreadViewModel(store, {uri, depth: 0})
     setView(newView)
-    newView
-      .setup()
-      .catch(err => store.log.error('Failed to fetch post', err.toString()))
+    newView.setup().catch(err => store.log.error('Failed to fetch post', err))
   }, [initView, uri, view?.params.uri, store])
 
   // deleted
@@ -112,12 +110,12 @@ export const Post = observer(function Post({
   const onPressToggleRepost = () => {
     item
       .toggleRepost()
-      .catch(e => store.log.error('Failed to toggle repost', e.toString()))
+      .catch(e => store.log.error('Failed to toggle repost', e))
   }
   const onPressToggleUpvote = () => {
     item
       .toggleUpvote()
-      .catch(e => store.log.error('Failed to toggle upvote', e.toString()))
+      .catch(e => store.log.error('Failed to toggle upvote', e))
   }
   const onCopyPostText = () => {
     Clipboard.setString(record.text)
@@ -130,7 +128,7 @@ export const Post = observer(function Post({
         Toast.show('Post deleted')
       },
       e => {
-        store.log.error('Failed to delete post', e.toString())
+        store.log.error('Failed to delete post', e)
         Toast.show('Failed to delete post, please try again')
       },
     )
diff --git a/src/view/com/post/PostText.tsx b/src/view/com/post/PostText.tsx
index 4e8761eb5..44f9e4d20 100644
--- a/src/view/com/post/PostText.tsx
+++ b/src/view/com/post/PostText.tsx
@@ -23,9 +23,7 @@ export const PostText = observer(function PostText({
     }
     const newModel = new PostModel(store, uri)
     setModel(newModel)
-    newModel
-      .setup()
-      .catch(err => store.log.error('Failed to fetch post', err.toString()))
+    newModel.setup().catch(err => store.log.error('Failed to fetch post', err))
   }, [uri, model?.uri, store])
 
   // loading
diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx
index 61ecf0a8f..f4dbc0c09 100644
--- a/src/view/com/posts/Feed.tsx
+++ b/src/view/com/posts/Feed.tsx
@@ -56,18 +56,13 @@ export const Feed = observer(function Feed({
     feed
       .refresh()
       .catch(err =>
-        feed.rootStore.log.error(
-          'Failed to refresh posts feed',
-          err.toString(),
-        ),
+        feed.rootStore.log.error('Failed to refresh posts feed', err),
       )
   }
   const onEndReached = () => {
     feed
       .loadMore()
-      .catch(err =>
-        feed.rootStore.log.error('Failed to load more posts', err.toString()),
-      )
+      .catch(err => feed.rootStore.log.error('Failed to load more posts', err))
   }
   let data
   if (feed.hasLoaded) {
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index dcc4e28d7..583d1548b 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -69,12 +69,12 @@ export const FeedItem = observer(function ({
   const onPressToggleRepost = () => {
     item
       .toggleRepost()
-      .catch(e => store.log.error('Failed to toggle repost', e.toString()))
+      .catch(e => store.log.error('Failed to toggle repost', e))
   }
   const onPressToggleUpvote = () => {
     item
       .toggleUpvote()
-      .catch(e => store.log.error('Failed to toggle upvote', e.toString()))
+      .catch(e => store.log.error('Failed to toggle upvote', e))
   }
   const onCopyPostText = () => {
     Clipboard.setString(record.text)
@@ -87,7 +87,7 @@ export const FeedItem = observer(function ({
         Toast.show('Post deleted')
       },
       e => {
-        store.log.error('Failed to delete post', e.toString())
+        store.log.error('Failed to delete post', e)
         Toast.show('Failed to delete post, please try again')
       },
     )
diff --git a/src/view/com/profile/ProfileFollowers.tsx b/src/view/com/profile/ProfileFollowers.tsx
index 409df05cb..e6e710ff3 100644
--- a/src/view/com/profile/ProfileFollowers.tsx
+++ b/src/view/com/profile/ProfileFollowers.tsx
@@ -29,9 +29,7 @@ export const ProfileFollowers = observer(function ProfileFollowers({
     setView(newView)
     newView
       .setup()
-      .catch(err =>
-        store.log.error('Failed to fetch user followers', err.toString()),
-      )
+      .catch(err => store.log.error('Failed to fetch user followers', err))
   }, [name, view?.params.user, store])
 
   const onRefresh = () => {
diff --git a/src/view/com/profile/ProfileFollows.tsx b/src/view/com/profile/ProfileFollows.tsx
index f63cc0107..73e765d19 100644
--- a/src/view/com/profile/ProfileFollows.tsx
+++ b/src/view/com/profile/ProfileFollows.tsx
@@ -29,9 +29,7 @@ export const ProfileFollows = observer(function ProfileFollows({
     setView(newView)
     newView
       .setup()
-      .catch(err =>
-        store.log.error('Failed to fetch user follows', err.toString()),
-      )
+      .catch(err => store.log.error('Failed to fetch user follows', err))
   }, [name, view?.params.user, store])
 
   const onRefresh = () => {
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 5a87401b4..a4d7c7a92 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -52,7 +52,7 @@ export const ProfileHeader = observer(function ProfileHeader({
           }`,
         )
       },
-      err => store.log.error('Failed to toggle follow', err.toString()),
+      err => store.log.error('Failed to toggle follow', err),
     )
   }
   const onPressEditProfile = () => {
@@ -94,7 +94,7 @@ export const ProfileHeader = observer(function ProfileHeader({
       await view.muteAccount()
       Toast.show('Account muted')
     } catch (e: any) {
-      store.log.error('Failed to mute account', e.toString())
+      store.log.error('Failed to mute account', e)
       Toast.show(`There was an issue! ${e.toString()}`)
     }
   }
@@ -103,7 +103,7 @@ export const ProfileHeader = observer(function ProfileHeader({
       await view.unmuteAccount()
       Toast.show('Account unmuted')
     } catch (e: any) {
-      store.log.error('Failed to unmute account', e.toString())
+      store.log.error('Failed to unmute account', e)
       Toast.show(`There was an issue! ${e.toString()}`)
     }
   }
diff --git a/src/view/com/profile/ProfileMembers.tsx b/src/view/com/profile/ProfileMembers.tsx
index bcba2a4da..7f566c198 100644
--- a/src/view/com/profile/ProfileMembers.tsx
+++ b/src/view/com/profile/ProfileMembers.tsx
@@ -22,7 +22,7 @@ export const ProfileMembers = observer(function ProfileMembers({
     setView(newView)
     newView
       .setup()
-      .catch(err => store.log.error('Failed to fetch members', err.toString()))
+      .catch(err => store.log.error('Failed to fetch members', err))
   }, [name, view?.params.actor, store])
 
   const onRefresh = () => {
diff --git a/src/view/lib/ThemeContext.tsx b/src/view/lib/ThemeContext.tsx
index f51983cb5..28edf1fc2 100644
--- a/src/view/lib/ThemeContext.tsx
+++ b/src/view/lib/ThemeContext.tsx
@@ -41,6 +41,7 @@ export type TypographyVariant =
   | 'caption'
   | 'overline1'
   | 'overline2'
+  | 'mono1'
 export type Typography = Record<TypographyVariant, TextStyle>
 
 export interface Theme {
diff --git a/src/view/lib/themes.ts b/src/view/lib/themes.ts
index 114d5cf99..45f55b116 100644
--- a/src/view/lib/themes.ts
+++ b/src/view/lib/themes.ts
@@ -1,3 +1,4 @@
+import {Platform} from 'react-native'
 import type {Theme} from './ThemeContext'
 import {colors} from './styles'
 
@@ -136,6 +137,10 @@ export const defaultTheme: Theme = {
       fontSize: 14,
       fontWeight: '600',
     },
+    mono1: {
+      fontSize: 14,
+      fontFamily: Platform.OS === 'android' ? 'monospace' : 'Courier New',
+    },
   },
 }
 
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
index dbf665837..17037c41a 100644
--- a/src/view/screens/Home.tsx
+++ b/src/view/screens/Home.tsx
@@ -37,7 +37,7 @@ export const Home = observer(function Home({
     }
     store.log.debug('Polling home feed')
     store.me.mainFeed.checkForLatest().catch(e => {
-      store.log.error('Failed to poll feed', e.toString())
+      store.log.error('Failed to poll feed', e)
     })
   }
 
diff --git a/src/view/screens/Log.tsx b/src/view/screens/Log.tsx
index 56337435f..86c5e50e2 100644
--- a/src/view/screens/Log.tsx
+++ b/src/view/screens/Log.tsx
@@ -65,10 +65,12 @@ export const Log = observer(function Log({navIdx, visible}: ScreenParams) {
                   </Text>
                 </TouchableOpacity>
                 {expanded.includes(entry.id) ? (
-                  <View style={[pal.btn, styles.details]}>
-                    <Text type="body1" style={pal.text}>
-                      {entry.details}
-                    </Text>
+                  <View style={[pal.view, s.pl10, s.pr10, s.pb10]}>
+                    <View style={[pal.btn, styles.details]}>
+                      <Text type="mono1" style={pal.text}>
+                        {entry.details}
+                      </Text>
+                    </View>
                   </View>
                 ) : undefined}
               </View>
diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx
index 5a4d9c223..7c9fac402 100644
--- a/src/view/screens/Notifications.tsx
+++ b/src/view/screens/Notifications.tsx
@@ -19,7 +19,7 @@ export const Notifications = ({navIdx, visible}: ScreenParams) => {
     store.me.notifications
       .update()
       .catch(e => {
-        store.log.error('Error while updating notifications feed', e.toString())
+        store.log.error('Error while updating notifications feed', e)
       })
       .then(() => {
         store.me.notifications.updateReadState()
diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx
index 86fde1374..eb8ac9eb4 100644
--- a/src/view/screens/PostThread.tsx
+++ b/src/view/screens/PostThread.tsx
@@ -38,7 +38,7 @@ export const PostThread = ({navIdx, visible, params}: ScreenParams) => {
           }
         },
         err => {
-          store.log.error('Failed to fetch thread', err.toString())
+          store.log.error('Failed to fetch thread', err)
         },
       )
     }
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index af011f837..0fb30162c 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -63,17 +63,14 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
     uiState
       .refresh()
       .catch((err: any) =>
-        store.log.error('Failed to refresh user profile', err.toString()),
+        store.log.error('Failed to refresh user profile', err),
       )
   }
   const onEndReached = () => {
     uiState
       .loadMore()
       .catch((err: any) =>
-        store.log.error(
-          'Failed to load more entries in user profile',
-          err.toString(),
-        ),
+        store.log.error('Failed to load more entries in user profile', err),
       )
   }
   const onPressTryAgain = () => {