diff --git a/changelog.d/6315.bugfix b/changelog.d/6315.bugfix
new file mode 100644
index 0000000000..0b5eb6064d
--- /dev/null
+++ b/changelog.d/6315.bugfix
@@ -0,0 +1 @@
+[Location sharing] Fix crash when starting/stopping a live when offline
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
index 11b74ecd7f..0f88f891cc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
@@ -46,14 +46,15 @@ interface LocationSharingService {
     /**
      * Starts sharing live location in the room.
      * @param timeoutMillis timeout of the live in milliseconds
-     * @return the id of the created beacon info event
+     * @return the result of the update of the live
      */
-    suspend fun startLiveLocationShare(timeoutMillis: Long): String
+    suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult
 
     /**
      * Stops sharing live location in the room.
+     * @return the result of the update of the live
      */
-    suspend fun stopLiveLocationShare()
+    suspend fun stopLiveLocationShare(): UpdateLiveLocationShareResult
 
     /**
      * Returns a LiveData on the list of current running live location shares.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/UpdateLiveLocationShareResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/UpdateLiveLocationShareResult.kt
new file mode 100644
index 0000000000..6f8c03be46
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/UpdateLiveLocationShareResult.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.api.session.room.location
+
+/**
+ * Represents the result of an update of live location share like a start or a stop.
+ */
+sealed interface UpdateLiveLocationShareResult {
+    data class Success(val beaconEventId: String) : UpdateLiveLocationShareResult
+    data class Failure(val error: Throwable) : UpdateLiveLocationShareResult
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt
index 3fa00fa077..015c1cca0b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt
@@ -22,6 +22,7 @@ import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import org.matrix.android.sdk.api.session.room.location.LocationSharingService
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
 import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary
 import org.matrix.android.sdk.api.util.Cancelable
 import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper
@@ -66,7 +67,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
         return sendLiveLocationTask.execute(params)
     }
 
-    override suspend fun startLiveLocationShare(timeoutMillis: Long): String {
+    override suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult {
         val params = StartLiveLocationShareTask.Params(
                 roomId = roomId,
                 timeoutMillis = timeoutMillis
@@ -74,7 +75,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
         return startLiveLocationShareTask.execute(params)
     }
 
-    override suspend fun stopLiveLocationShare() {
+    override suspend fun stopLiveLocationShare(): UpdateLiveLocationShareResult {
         val params = StopLiveLocationShareTask.Params(
                 roomId = roomId,
         )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt
index 7da67d7539..b943c27977 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room.location
 
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
 import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.session.room.state.SendStateTask
@@ -25,7 +26,7 @@ import org.matrix.android.sdk.internal.task.Task
 import org.matrix.android.sdk.internal.util.time.Clock
 import javax.inject.Inject
 
-internal interface StartLiveLocationShareTask : Task<StartLiveLocationShareTask.Params, String> {
+internal interface StartLiveLocationShareTask : Task<StartLiveLocationShareTask.Params, UpdateLiveLocationShareResult> {
     data class Params(
             val roomId: String,
             val timeoutMillis: Long,
@@ -38,7 +39,7 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor(
         private val sendStateTask: SendStateTask,
 ) : StartLiveLocationShareTask {
 
-    override suspend fun execute(params: StartLiveLocationShareTask.Params): String {
+    override suspend fun execute(params: StartLiveLocationShareTask.Params): UpdateLiveLocationShareResult {
         val beaconContent = MessageBeaconInfoContent(
                 timeout = params.timeoutMillis,
                 isLive = true,
@@ -51,6 +52,15 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor(
                 eventType = eventType,
                 body = beaconContent
         )
-        return sendStateTask.executeRetry(sendStateTaskParams, 3)
+        return try {
+            val eventId = sendStateTask.executeRetry(sendStateTaskParams, 3)
+            if (eventId.isNotEmpty()) {
+                UpdateLiveLocationShareResult.Success(eventId)
+            } else {
+                UpdateLiveLocationShareResult.Failure(Exception("empty event id for new state event"))
+            }
+        } catch (error: Throwable) {
+            UpdateLiveLocationShareResult.Failure(error)
+        }
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt
index 1c282684a4..d0e7ff3f82 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StopLiveLocationShareTask.kt
@@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toContent
 import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
 import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.session.room.state.SendStateTask
@@ -29,7 +30,7 @@ import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
 import org.matrix.android.sdk.internal.task.Task
 import javax.inject.Inject
 
-internal interface StopLiveLocationShareTask : Task<StopLiveLocationShareTask.Params, Unit> {
+internal interface StopLiveLocationShareTask : Task<StopLiveLocationShareTask.Params, UpdateLiveLocationShareResult> {
     data class Params(
             val roomId: String,
     )
@@ -41,10 +42,10 @@ internal class DefaultStopLiveLocationShareTask @Inject constructor(
         private val stateEventDataSource: StateEventDataSource,
 ) : StopLiveLocationShareTask {
 
-    override suspend fun execute(params: StopLiveLocationShareTask.Params) {
-        val beaconInfoStateEvent = getLiveLocationBeaconInfoForUser(userId, params.roomId) ?: return
-        val stateKey = beaconInfoStateEvent.stateKey ?: return
-        val content = beaconInfoStateEvent.getClearContent()?.toModel<MessageBeaconInfoContent>() ?: return
+    override suspend fun execute(params: StopLiveLocationShareTask.Params): UpdateLiveLocationShareResult {
+        val beaconInfoStateEvent = getLiveLocationBeaconInfoForUser(userId, params.roomId) ?: return getResultForIncorrectBeaconInfoEvent()
+        val stateKey = beaconInfoStateEvent.stateKey ?: return getResultForIncorrectBeaconInfoEvent()
+        val content = beaconInfoStateEvent.getClearContent()?.toModel<MessageBeaconInfoContent>() ?: return getResultForIncorrectBeaconInfoEvent()
         val updatedContent = content.copy(isLive = false).toContent()
         val sendStateTaskParams = SendStateTask.Params(
                 roomId = params.roomId,
@@ -52,9 +53,21 @@ internal class DefaultStopLiveLocationShareTask @Inject constructor(
                 eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
                 body = updatedContent
         )
-        sendStateTask.executeRetry(sendStateTaskParams, 3)
+        return try {
+            val eventId = sendStateTask.executeRetry(sendStateTaskParams, 3)
+            if (eventId.isNotEmpty()) {
+                UpdateLiveLocationShareResult.Success(eventId)
+            } else {
+                UpdateLiveLocationShareResult.Failure(Exception("empty event id for new state event"))
+            }
+        } catch (error: Throwable) {
+            UpdateLiveLocationShareResult.Failure(error)
+        }
     }
 
+    private fun getResultForIncorrectBeaconInfoEvent() =
+            UpdateLiveLocationShareResult.Failure(Exception("incorrect last beacon info event"))
+
     private fun getLiveLocationBeaconInfoForUser(userId: String, roomId: String): Event? {
         return EventType.STATE_ROOM_BEACON_INFO
                 .mapNotNull {
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt
index 003842be28..30a9671733 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingServiceTest.kt
@@ -18,15 +18,14 @@ package org.matrix.android.sdk.internal.session.room.location
 
 import io.mockk.coEvery
 import io.mockk.coVerify
-import io.mockk.just
 import io.mockk.mockk
-import io.mockk.runs
 import io.mockk.unmockkAll
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
 import org.amshove.kluent.shouldBeEqualTo
 import org.junit.After
 import org.junit.Test
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
 import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary
 import org.matrix.android.sdk.api.util.Cancelable
 import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper
@@ -119,11 +118,11 @@ internal class DefaultLocationSharingServiceTest {
 
     @Test
     fun `live location share can be started with a given timeout`() = runTest {
-        coEvery { startLiveLocationShareTask.execute(any()) } returns AN_EVENT_ID
+        coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
 
-        val eventId = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
+        val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
 
-        eventId shouldBeEqualTo AN_EVENT_ID
+        result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
         val expectedParams = StartLiveLocationShareTask.Params(
                 roomId = A_ROOM_ID,
                 timeoutMillis = A_TIMEOUT
@@ -133,10 +132,11 @@ internal class DefaultLocationSharingServiceTest {
 
     @Test
     fun `live location share can be stopped`() = runTest {
-        coEvery { stopLiveLocationShareTask.execute(any()) } just runs
+        coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
 
-        defaultLocationSharingService.stopLiveLocationShare()
+        val result = defaultLocationSharingService.stopLiveLocationShare()
 
+        result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
         val expectedParams = StopLiveLocationShareTask.Params(
                 roomId = A_ROOM_ID
         )
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt
index c435e60db3..909ba5d048 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStartLiveLocationShareTaskTest.kt
@@ -20,10 +20,12 @@ import io.mockk.unmockkAll
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
 import org.amshove.kluent.shouldBeEqualTo
+import org.amshove.kluent.shouldBeInstanceOf
 import org.junit.After
 import org.junit.Test
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
 import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
 import org.matrix.android.sdk.internal.session.room.state.SendStateTask
 import org.matrix.android.sdk.test.fakes.FakeClock
@@ -53,7 +55,7 @@ internal class DefaultStartLiveLocationShareTaskTest {
     }
 
     @Test
-    fun `given parameters when calling the task then it is correctly executed`() = runTest {
+    fun `given parameters and no error when calling the task then result is success`() = runTest {
         val params = StartLiveLocationShareTask.Params(
                 roomId = A_ROOM_ID,
                 timeoutMillis = A_TIMEOUT
@@ -63,7 +65,7 @@ internal class DefaultStartLiveLocationShareTaskTest {
 
         val result = defaultStartLiveLocationShareTask.execute(params)
 
-        result shouldBeEqualTo AN_EVENT_ID
+        result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
         val expectedBeaconContent = MessageBeaconInfoContent(
                 timeout = params.timeoutMillis,
                 isLive = true,
@@ -80,4 +82,33 @@ internal class DefaultStartLiveLocationShareTaskTest {
                 remainingRetry = 3
         )
     }
+
+    @Test
+    fun `given parameters and an empty returned event id when calling the task then result is failure`() = runTest {
+        val params = StartLiveLocationShareTask.Params(
+                roomId = A_ROOM_ID,
+                timeoutMillis = A_TIMEOUT
+        )
+        fakeClock.givenEpoch(AN_EPOCH)
+        fakeSendStateTask.givenExecuteRetryReturns("")
+
+        val result = defaultStartLiveLocationShareTask.execute(params)
+
+        result shouldBeInstanceOf UpdateLiveLocationShareResult.Failure::class
+    }
+
+    @Test
+    fun `given parameters and error during event sending when calling the task then result is failure`() = runTest {
+        val params = StartLiveLocationShareTask.Params(
+                roomId = A_ROOM_ID,
+                timeoutMillis = A_TIMEOUT
+        )
+        fakeClock.givenEpoch(AN_EPOCH)
+        val error = Throwable()
+        fakeSendStateTask.givenExecuteRetryThrows(error)
+
+        val result = defaultStartLiveLocationShareTask.execute(params)
+
+        result shouldBeEqualTo UpdateLiveLocationShareResult.Failure(error)
+    }
 }
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt
index 81a5742f90..7cb5abff62 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/room/location/DefaultStopLiveLocationShareTaskTest.kt
@@ -19,11 +19,15 @@ package org.matrix.android.sdk.internal.session.room.location
 import io.mockk.unmockkAll
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
+import org.amshove.kluent.shouldBeEqualTo
+import org.amshove.kluent.shouldBeInstanceOf
 import org.junit.After
 import org.junit.Test
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
+import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
 import org.matrix.android.sdk.internal.session.room.state.SendStateTask
 import org.matrix.android.sdk.test.fakes.FakeSendStateTask
@@ -53,7 +57,7 @@ class DefaultStopLiveLocationShareTaskTest {
     }
 
     @Test
-    fun `given parameters when calling the task then it is correctly executed`() = runTest {
+    fun `given parameters and no error when calling the task then result is success`() = runTest {
         val params = StopLiveLocationShareTask.Params(roomId = A_ROOM_ID)
         val currentStateEvent = Event(
                 stateKey = A_USER_ID,
@@ -66,8 +70,9 @@ class DefaultStopLiveLocationShareTaskTest {
         fakeStateEventDataSource.givenGetStateEventReturns(currentStateEvent)
         fakeSendStateTask.givenExecuteRetryReturns(AN_EVENT_ID)
 
-        defaultStopLiveLocationShareTask.execute(params)
+        val result = defaultStopLiveLocationShareTask.execute(params)
 
+        result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
         val expectedBeaconContent = MessageBeaconInfoContent(
                 timeout = A_TIMEOUT,
                 isLive = false,
@@ -89,4 +94,78 @@ class DefaultStopLiveLocationShareTaskTest {
                 stateKey = A_USER_ID
         )
     }
+
+    @Test
+    fun `given parameters and an incorrect current state event when calling the task then result is failure`() = runTest {
+        val incorrectCurrentStateEvents = listOf(
+                // no event
+                null,
+                // no stateKey
+                Event(
+                        stateKey = null,
+                        content = MessageBeaconInfoContent(
+                                timeout = A_TIMEOUT,
+                                isLive = true,
+                                unstableTimestampMillis = AN_EPOCH
+                        ).toContent()
+                ),
+                // incorrect content
+                Event(
+                        stateKey = A_USER_ID,
+                        content = MessageAudioContent(
+                                msgType = "",
+                                body = ""
+                        ).toContent()
+                )
+        )
+
+        incorrectCurrentStateEvents.forEach { currentStateEvent ->
+            fakeStateEventDataSource.givenGetStateEventReturns(currentStateEvent)
+            fakeSendStateTask.givenExecuteRetryReturns(AN_EVENT_ID)
+            val params = StopLiveLocationShareTask.Params(roomId = A_ROOM_ID)
+
+            val result = defaultStopLiveLocationShareTask.execute(params)
+
+            result shouldBeInstanceOf UpdateLiveLocationShareResult.Failure::class
+        }
+    }
+
+    @Test
+    fun `given parameters and an empty returned event id when calling the task then result is failure`() = runTest {
+        val params = StopLiveLocationShareTask.Params(roomId = A_ROOM_ID)
+        val currentStateEvent = Event(
+                stateKey = A_USER_ID,
+                content = MessageBeaconInfoContent(
+                        timeout = A_TIMEOUT,
+                        isLive = true,
+                        unstableTimestampMillis = AN_EPOCH
+                ).toContent()
+        )
+        fakeStateEventDataSource.givenGetStateEventReturns(currentStateEvent)
+        fakeSendStateTask.givenExecuteRetryReturns("")
+
+        val result = defaultStopLiveLocationShareTask.execute(params)
+
+        result shouldBeInstanceOf UpdateLiveLocationShareResult.Failure::class
+    }
+
+    @Test
+    fun `given parameters and error during event sending when calling the task then result is failure`() = runTest {
+        val params = StopLiveLocationShareTask.Params(roomId = A_ROOM_ID)
+        val currentStateEvent = Event(
+                stateKey = A_USER_ID,
+                content = MessageBeaconInfoContent(
+                        timeout = A_TIMEOUT,
+                        isLive = true,
+                        unstableTimestampMillis = AN_EPOCH
+                ).toContent()
+        )
+        fakeStateEventDataSource.givenGetStateEventReturns(currentStateEvent)
+        val error = Throwable()
+        fakeSendStateTask.givenExecuteRetryThrows(error)
+
+        val result = defaultStopLiveLocationShareTask.execute(params)
+
+        result shouldBeEqualTo UpdateLiveLocationShareResult.Failure(error)
+    }
 }
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSendStateTask.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSendStateTask.kt
index 0999ba619b..08a25be93e 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSendStateTask.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeSendStateTask.kt
@@ -27,6 +27,10 @@ internal class FakeSendStateTask : SendStateTask by mockk() {
         coEvery { executeRetry(any(), any()) } returns eventId
     }
 
+    fun givenExecuteRetryThrows(error: Throwable) {
+        coEvery { executeRetry(any(), any()) } throws error
+    }
+
     fun verifyExecuteRetry(params: SendStateTask.Params, remainingRetry: Int) {
         coVerify { executeRetry(params, remainingRetry) }
     }
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeStateEventDataSource.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeStateEventDataSource.kt
index 498901bdac..ca03316fa7 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeStateEventDataSource.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fakes/FakeStateEventDataSource.kt
@@ -27,7 +27,7 @@ internal class FakeStateEventDataSource {
 
     val instance: StateEventDataSource = mockk()
 
-    fun givenGetStateEventReturns(event: Event) {
+    fun givenGetStateEventReturns(event: Event?) {
         every {
             instance.getStateEvent(
                     roomId = any(),
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
index 07b20b4914..1c2255246b 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
@@ -1293,6 +1293,10 @@ class TimelineViewModel @AssistedInject constructor(
         locationSharingServiceConnection.bind(this)
     }
 
+    override fun onLocationServiceError(error: Throwable) {
+        _viewEvents.post(RoomDetailViewEvents.Failure(throwable = error, showInDialog = true))
+    }
+
     override fun onCleared() {
         timeline.dispose()
         timeline.removeAllListeners()
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt
index 77f3abcc28..ef612eeec2 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt
@@ -30,6 +30,7 @@ import kotlinx.coroutines.launch
 import kotlinx.parcelize.Parcelize
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.getRoom
+import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
 import timber.log.Timber
 import java.util.Timer
 import java.util.TimerTask
@@ -54,8 +55,9 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
     /**
      * Keep track of a map between beacon event Id starting the live and RoomArgs.
      */
-    private var roomArgsMap = mutableMapOf<String, RoomArgs>()
-    private var timers = mutableListOf<Timer>()
+    private val roomArgsMap = mutableMapOf<String, RoomArgs>()
+    private val timers = mutableListOf<Timer>()
+    var callback: Callback? = null
 
     override fun onCreate() {
         super.onCreate()
@@ -89,19 +91,27 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
     }
 
     private suspend fun sendStartingLiveBeaconInfo(session: Session, roomArgs: RoomArgs) {
-        val beaconEventId = session
+        val updateLiveResult = session
                 .getRoom(roomArgs.roomId)
                 ?.locationSharingService()
                 ?.startLiveLocationShare(timeoutMillis = roomArgs.durationMillis)
 
-        beaconEventId
-                ?.takeUnless { it.isEmpty() }
-                ?.let {
-                    roomArgsMap[it] = roomArgs
-                    locationTracker.requestLastKnownLocation()
+        updateLiveResult
+                ?.let { result ->
+                    when (result) {
+                        is UpdateLiveLocationShareResult.Success -> {
+                            roomArgsMap[result.beaconEventId] = roomArgs
+                            locationTracker.requestLastKnownLocation()
+                        }
+                        is UpdateLiveLocationShareResult.Failure -> {
+                            callback?.onServiceError(result.error)
+                            tryToDestroyMe()
+                        }
+                    }
                 }
                 ?: run {
                     Timber.w("### LocationSharingService.sendStartingLiveBeaconInfo error, no received beacon info id")
+                    tryToDestroyMe()
                 }
     }
 
@@ -123,28 +133,28 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
     fun stopSharingLocation(roomId: String) {
         Timber.i("### LocationSharingService.stopSharingLocation for $roomId")
 
-        // Send a new beacon info state by setting live field as false
-        sendStoppedBeaconInfo(roomId)
+        launchInIO { session ->
+            when (val result = sendStoppedBeaconInfo(session, roomId)) {
+                is UpdateLiveLocationShareResult.Success -> {
+                    synchronized(roomArgsMap) {
+                        val beaconIds = roomArgsMap
+                                .filter { it.value.roomId == roomId }
+                                .map { it.key }
+                        beaconIds.forEach { roomArgsMap.remove(it) }
 
-        synchronized(roomArgsMap) {
-            val beaconIds = roomArgsMap
-                    .filter { it.value.roomId == roomId }
-                    .map { it.key }
-            beaconIds.forEach { roomArgsMap.remove(it) }
-
-            if (roomArgsMap.isEmpty()) {
-                Timber.i("### LocationSharingService. Destroying self, time is up for all rooms")
-                destroyMe()
+                        tryToDestroyMe()
+                    }
+                }
+                is UpdateLiveLocationShareResult.Failure -> callback?.onServiceError(result.error)
+                else -> Unit
             }
         }
     }
 
-    private fun sendStoppedBeaconInfo(roomId: String) {
-        launchInIO { session ->
-            session.getRoom(roomId)
-                    ?.locationSharingService()
-                    ?.stopLiveLocationShare()
-        }
+    private suspend fun sendStoppedBeaconInfo(session: Session, roomId: String): UpdateLiveLocationShareResult? {
+        return session.getRoom(roomId)
+                ?.locationSharingService()
+                ?.stopLiveLocationShare()
     }
 
     override fun onLocationUpdate(locationData: LocationData) {
@@ -178,6 +188,13 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
         stopSelf()
     }
 
+    private fun tryToDestroyMe() {
+        if (roomArgsMap.isEmpty()) {
+            Timber.i("### LocationSharingService. Destroying self, time is up for all rooms")
+            destroyMe()
+        }
+    }
+
     private fun destroyMe() {
         locationTracker.removeCallback(this)
         timers.forEach { it.cancel() }
@@ -209,6 +226,10 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
         fun getService(): LocationSharingService = this@LocationSharingService
     }
 
+    interface Callback {
+        fun onServiceError(error: Throwable)
+    }
+
     companion object {
         const val EXTRA_ROOM_ARGS = "EXTRA_ROOM_ARGS"
     }
diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt
index e72f77531b..af09e0b1e0 100644
--- a/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt
+++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt
@@ -25,11 +25,12 @@ import javax.inject.Inject
 
 class LocationSharingServiceConnection @Inject constructor(
         private val context: Context
-) : ServiceConnection {
+) : ServiceConnection, LocationSharingService.Callback {
 
     interface Callback {
         fun onLocationServiceRunning()
         fun onLocationServiceStopped()
+        fun onLocationServiceError(error: Throwable)
     }
 
     private var callback: Callback? = null
@@ -57,14 +58,21 @@ class LocationSharingServiceConnection @Inject constructor(
     }
 
     override fun onServiceConnected(className: ComponentName, binder: IBinder) {
-        locationSharingService = (binder as LocationSharingService.LocalBinder).getService()
+        locationSharingService = (binder as LocationSharingService.LocalBinder).getService().also {
+            it.callback = this
+        }
         isBound = true
         callback?.onLocationServiceRunning()
     }
 
     override fun onServiceDisconnected(className: ComponentName) {
         isBound = false
+        locationSharingService?.callback = null
         locationSharingService = null
         callback?.onLocationServiceStopped()
     }
+
+    override fun onServiceError(error: Throwable) {
+        callback?.onLocationServiceError(error)
+    }
 }
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt
index 6645ff58d9..23771299c8 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewEvents.kt
@@ -18,4 +18,6 @@ package im.vector.app.features.location.live.map
 
 import im.vector.app.core.platform.VectorViewEvents
 
-sealed interface LocationLiveMapViewEvents : VectorViewEvents
+sealed interface LocationLiveMapViewEvents : VectorViewEvents {
+    data class Error(val error: Throwable) : LocationLiveMapViewEvents
+}
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt
index 5f2410d697..a57ba74685 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewFragment.kt
@@ -76,6 +76,8 @@ class LocationLiveMapViewFragment @Inject constructor() : VectorBaseFragment<Fra
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
+        observeViewEvents()
+
         views.liveLocationBottomSheetRecyclerView.configureWith(bottomSheetController, hasFixedSize = false, disableItemAnimation = true)
 
         bottomSheetController.callback = object : LiveLocationBottomSheetController.Callback {
@@ -89,6 +91,14 @@ class LocationLiveMapViewFragment @Inject constructor() : VectorBaseFragment<Fra
         }
     }
 
+    private fun observeViewEvents() {
+        viewModel.observeViewEvents { viewEvent ->
+            when (viewEvent) {
+                is LocationLiveMapViewEvents.Error -> displayErrorDialog(viewEvent.error)
+            }
+        }
+    }
+
     override fun onResume() {
         super.onResume()
         setupMap()
diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt
index eb5bccff0f..e89649709a 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/map/LocationLiveMapViewModel.kt
@@ -80,4 +80,8 @@ class LocationLiveMapViewModel @AssistedInject constructor(
     override fun onLocationServiceStopped() {
         // NOOP
     }
+
+    override fun onLocationServiceError(error: Throwable) {
+        _viewEvents.post(LocationLiveMapViewEvents.Error(error))
+    }
 }