diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index b43161a13..a3c294bc3 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -222,6 +222,7 @@ static void setup_free(struct a2dp_setup *s)
 		avdtp_unref(s->session);
 	g_slist_free_full(s->cb, g_free);
 	g_slist_free_full(s->caps, g_free);
+	g_free(s->err);
 	g_free(s);
 }
 
@@ -270,17 +271,34 @@ static void setup_cb_free(struct a2dp_setup_cb *cb)
 	g_free(cb);
 }
 
+static void setup_error_set(struct a2dp_setup *setup, struct avdtp_error *err)
+{
+	if (!err) {
+		g_free(setup->err);
+		setup->err = NULL;
+	} else {
+		if (!setup->err)
+			setup->err = g_new0(struct avdtp_error, 1);
+		memcpy(setup->err, err, sizeof(struct avdtp_error));
+	}
+}
+
+static void setup_error_init(struct a2dp_setup *setup, uint8_t type, int id)
+{
+	struct avdtp_error err;
+
+	avdtp_error_init(&err, type, id);
+	setup_error_set(setup, &err);
+}
+
 static void finalize_setup_errno(struct a2dp_setup *s, int err,
 					GSourceFunc cb1, ...)
 {
 	GSourceFunc finalize;
 	va_list args;
-	struct avdtp_error avdtp_err;
 
-	if (err < 0) {
-		avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
-		s->err = &avdtp_err;
-	}
+	if (err < 0)
+		setup_error_init(s, AVDTP_ERRNO, -err);
 
 	va_start(args, cb1);
 	finalize = cb1;
@@ -576,10 +594,7 @@ done:
 
 	finalize_config(setup);
 
-	if (setup->err) {
-		g_free(setup->err);
-		setup->err = NULL;
-	}
+	setup_error_set(setup, NULL);
 
 	setup_unref(setup);
 
@@ -588,11 +603,9 @@ done:
 
 static void endpoint_setconf_cb(struct a2dp_setup *setup, gboolean ret)
 {
-	if (ret == FALSE) {
-		setup->err = g_new(struct avdtp_error, 1);
-		avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
+	if (ret == FALSE)
+		setup_error_init(setup, AVDTP_MEDIA_CODEC,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
-	}
 
 	auto_config(setup);
 	setup_unref(setup);
@@ -671,8 +684,7 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
 
 		if (cap->category == AVDTP_DELAY_REPORTING &&
 					!a2dp_sep->delay_reporting) {
-			setup->err = g_new(struct avdtp_error, 1);
-			avdtp_error_init(setup->err, AVDTP_DELAY_REPORTING,
+			setup_error_init(setup, AVDTP_DELAY_REPORTING,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
 			goto done;
 		}
@@ -683,8 +695,7 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
 		codec = (struct avdtp_media_codec_capability *) cap->data;
 
 		if (codec->media_codec_type != a2dp_sep->codec) {
-			setup->err = g_new(struct avdtp_error, 1);
-			avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
+			setup_error_init(setup, AVDTP_MEDIA_CODEC,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
 			goto done;
 		}
@@ -704,10 +715,9 @@ static gboolean endpoint_setconf_ind(struct avdtp *session,
 			return TRUE;
 		}
 
-		setup_unref(setup);
-		setup->err = g_new(struct avdtp_error, 1);
-		avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
+		setup_error_init(setup, AVDTP_MEDIA_CODEC,
 					AVDTP_UNSUPPORTED_CONFIGURATION);
+		setup_unref(setup);
 		break;
 	}
 
@@ -886,7 +896,7 @@ static void invalidate_remote_cache(struct a2dp_setup *setup,
 		/* Set error to -EAGAIN so the likes of policy plugin can
 		 * reattempt to connect.
 		 */
-		avdtp_error_init(setup->err, AVDTP_ERRNO, -EAGAIN);
+		setup_error_init(setup, AVDTP_ERRNO, -EAGAIN);
 	}
 }
 
@@ -910,10 +920,10 @@ static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 	if (err) {
 		if (setup) {
 			setup_ref(setup);
-			setup->err = err;
+			setup_error_set(setup, err);
 			invalidate_remote_cache(setup, err);
 			finalize_config(setup);
-			setup->err = NULL;
+			setup_error_set(setup, NULL);
 			setup_unref(setup);
 		}
 
@@ -1116,7 +1126,7 @@ static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 		if (setup->start)
 			finalize_resume(setup);
 	} else if (setup->chan)
@@ -1191,7 +1201,7 @@ static void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 	}
 
 	finalize_resume(setup);
@@ -1270,7 +1280,7 @@ static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 	}
 
 	finalize_suspend(setup);
@@ -1418,7 +1428,7 @@ static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 		finalize_config(setup);
 		return;
 	}
@@ -1528,7 +1538,7 @@ static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
 
 	if (err) {
 		setup->stream = NULL;
-		setup->err = err;
+		setup_error_set(setup, err);
 	}
 
 	finalize_config(setup);
@@ -2885,7 +2895,7 @@ static void discover_cb(struct avdtp *session, GSList *seps,
 
 	setup->seps = seps;
 	if (err)
-		setup->err = err;
+		setup_error_set(setup, err);
 
 	if (!err) {
 		g_slist_foreach(seps, foreach_register_remote_sep, setup->chan);
