diff --git a/lib/logger/__snapshots__/err-serializer.spec.ts.snap b/lib/logger/__snapshots__/err-serializer.spec.ts.snap
index 99b318b08bb5ef90baf8d4a42cc684a077ecfc81..8fb0bda601dfc318333ab39b5e35e9e7d59edc8a 100644
--- a/lib/logger/__snapshots__/err-serializer.spec.ts.snap
+++ b/lib/logger/__snapshots__/err-serializer.spec.ts.snap
@@ -33,7 +33,23 @@ Array [
 ]
 `;
 
-exports[`logger/err-serializer got handles http error 2`] = `
+exports[`logger/err-serializer got sanitize http error 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic OnRva2Vu",
+      "host": "github.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+    },
+    "method": "POST",
+    "url": "https://:token@github.com/api",
+  },
+]
+`;
+
+exports[`logger/err-serializer got sanitize http error 2`] = `
 Object {
   "code": undefined,
   "message": "Response code 412 (Precondition Failed)",
diff --git a/lib/logger/err-serializer.spec.ts b/lib/logger/err-serializer.spec.ts
index 2aa9d3ff76a9b2c7cdfd59eafd53372baf0208b2..16237ef8f2f045e6b0cec711e28816552cc740e4 100644
--- a/lib/logger/err-serializer.spec.ts
+++ b/lib/logger/err-serializer.spec.ts
@@ -2,7 +2,7 @@ import * as httpMock from '../../test/httpMock';
 import { partial } from '../../test/util';
 import * as hostRules from '../util/host-rules';
 import { Http } from '../util/http';
-import configSerializer from './err-serializer';
+import errSerializer from './err-serializer';
 import { sanitizeValue } from './utils';
 
 describe('logger/err-serializer', () => {
@@ -21,7 +21,7 @@ describe('logger/err-serializer', () => {
         },
       },
     });
-    expect(configSerializer(err)).toMatchSnapshot();
+    expect(errSerializer(err)).toMatchSnapshot();
   });
   it('handles missing fields', () => {
     const err = partial<Error & Record<string, unknown>>({
@@ -29,7 +29,7 @@ describe('logger/err-serializer', () => {
       stack: 'foo',
       body: 'some body',
     });
-    expect(configSerializer(err)).toMatchSnapshot();
+    expect(errSerializer(err)).toMatchSnapshot();
   });
 
   describe('got', () => {
@@ -58,14 +58,29 @@ describe('logger/err-serializer', () => {
       try {
         await new Http('any').postJson('https://:token@github.com/api');
       } catch (error) {
-        err = configSerializer(error);
+        err = errSerializer(error);
       }
 
       expect(httpMock.getTrace()).toMatchSnapshot();
       expect(err).toBeDefined();
-
       expect(err.response.body).toBeDefined();
       expect(err.options).toBeDefined();
+    });
+
+    it('sanitize http error', async () => {
+      httpMock
+        .scope(baseUrl)
+        .post('/api')
+        .reply(412, { err: { message: 'failed' } });
+      let err: any;
+      try {
+        await new Http('any').postJson('https://:token@github.com/api');
+      } catch (error) {
+        err = error;
+      }
+
+      expect(httpMock.getTrace()).toMatchSnapshot();
+      expect(err).toBeDefined();
 
       // remove platform related props
       delete err.timings;
diff --git a/lib/logger/err-serializer.ts b/lib/logger/err-serializer.ts
index 9aa9dc30a815d5c10d1129fe44332aa246ee1524..82b8b2963ebe0558db8dc9aecb946fe17b12f6e0 100644
--- a/lib/logger/err-serializer.ts
+++ b/lib/logger/err-serializer.ts
@@ -1,46 +1,10 @@
 import is from '@sindresorhus/is';
-import { RequestError } from 'got';
-import { clone } from '../util/clone';
+import prepareError from './utils';
 
 Error.stackTraceLimit = 20;
 
 export default function errSerializer(err: Error): any {
-  const response: Record<string, unknown> = {
-    ...err,
-  };
-
-  // Can maybe removed?
-  if (!response.message && err.message) {
-    response.message = err.message;
-  }
-
-  // Can maybe removed?
-  if (!response.stack && err.stack) {
-    response.stack = err.stack;
-  }
-
-  // handle got error
-  if (err instanceof RequestError) {
-    const options: Record<string, unknown> = {
-      headers: clone(err.options.headers),
-      url: err.options.url?.toString(),
-    };
-    response.options = options;
-
-    for (const k of ['username', 'password', 'method', 'http2']) {
-      options[k] = err.options[k];
-    }
-
-    if (err.response) {
-      response.response = {
-        statusCode: err.response?.statusCode,
-        statusMessage: err.response?.statusMessage,
-        body: clone(err.response.body),
-        headers: clone(err.response.headers),
-        httpVersion: err.response.httpVersion,
-      };
-    }
-  }
+  const response: Record<string, unknown> = prepareError(err);
 
   // already done by `sanitizeValue` ?
   const redactedFields = ['message', 'stack', 'stdout', 'stderr'];
diff --git a/lib/logger/index.ts b/lib/logger/index.ts
index 9e06d13b33ccdf12de9bcfc8f8dd8f760c8aa487..2d8e3ed7757a3b612425d134ea9767993fcdd7fc 100644
--- a/lib/logger/index.ts
+++ b/lib/logger/index.ts
@@ -21,10 +21,13 @@ const problems = new ProblemStream();
 
 const stdout: bunyan.Stream = {
   name: 'stdout',
-  level: (process.env.LOG_LEVEL as bunyan.LogLevel) || 'info',
+  level:
+    (process.env.LOG_LEVEL as bunyan.LogLevel) ||
+    /* istanbul ignore next: not testable */ 'info',
   stream: process.stdout,
 };
 
+// istanbul ignore else: not testable
 if (process.env.LOG_FORMAT !== 'json') {
   // TODO: typings
   const prettyStdOut = new RenovateStream() as any;
diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts
index 4cf60954eb3502dc5debcc059c3359ff69225ef7..955f088d3f0c21d0fbb603f050f2736a2ccd9bd6 100644
--- a/lib/logger/utils.ts
+++ b/lib/logger/utils.ts
@@ -1,6 +1,8 @@
 import { Stream } from 'stream';
 import bunyan from 'bunyan';
 import fs from 'fs-extra';
+import { RequestError } from 'got';
+import { clone } from '../util/clone';
 import { redactedFields, sanitize } from '../util/sanitize';
 
 export interface BunyanRecord extends Record<string, any> {
@@ -49,6 +51,48 @@ const contentFields = [
   'yarnLockParsed',
 ];
 
+export default function prepareError(err: Error): Record<string, unknown> {
+  const response: Record<string, unknown> = {
+    ...err,
+  };
+
+  // Required as message is non-enumerable
+  if (!response.message && err.message) {
+    response.message = err.message;
+  }
+
+  // Required as stack is non-enumerable
+  if (!response.stack && err.stack) {
+    response.stack = err.stack;
+  }
+
+  // handle got error
+  if (err instanceof RequestError) {
+    const options: Record<string, unknown> = {
+      headers: clone(err.options.headers),
+      url: err.options.url?.toString(),
+    };
+    response.options = options;
+
+    for (const k of ['username', 'password', 'method', 'http2']) {
+      options[k] = err.options[k];
+    }
+
+    // istanbul ignore else
+    if (err.response) {
+      response.response = {
+        statusCode: err.response?.statusCode,
+        statusMessage: err.response?.statusMessage,
+        body: clone(err.response.body),
+        headers: clone(err.response.headers),
+        httpVersion: err.response.httpVersion,
+      };
+    }
+  }
+
+  return response;
+}
+
 export function sanitizeValue(value: unknown, seen = new WeakMap()): any {
   if (Array.isArray(value)) {
     const length = value.length;
@@ -67,6 +111,11 @@ export function sanitizeValue(value: unknown, seen = new WeakMap()): any {
     return '[content]';
   }
 
+  if (value instanceof Error) {
+    // eslint-disable-next-line no-param-reassign
+    value = prepareError(value);
+  }
+
   const valueType = typeof value;
 
   if (value != null && valueType !== 'function' && valueType === 'object') {