diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java
index b53be2a88c4aba70ef316d198fc15dd5c3c2adcb..a1b095a22501d26fff2970b0fca405abcc626fb7 100644
--- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java
+++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java
@@ -30,6 +30,9 @@ import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 import java.time.ZonedDateTime;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
 import java.util.stream.Stream;
 
 import org.apache.commons.io.IOUtils;
@@ -39,6 +42,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 
 import com.google.protobuf.ByteString;
 
+import de.ozgcloud.apilib.common.errorhandling.NotFoundException;
 import de.ozgcloud.apilib.file.OzgCloudFile;
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.nachrichten.NachrichtenManagerConfiguration;
@@ -133,17 +137,22 @@ class AntragraumGrpcService extends AntragraumServiceGrpc.AntragraumServiceImplB
 
 	@Override
 	public void getAttachmentContent(GrpcGetAttachmentContentRequest request, StreamObserver<GrpcGetAttachmentContentResponse> responseObserver) {
-		try (var pipedInputStream = new PipedInputStream(); var pipedOutputStream = new PipedOutputStream(pipedInputStream)) {
-			getAttachmentFileContent(request, pipedOutputStream);
+		try (var pipedInputStream = new PipedInputStream();
+				var pipedOutputStream = new PipedOutputStream(pipedInputStream);
+				var executor = Executors.newFixedThreadPool(1);) {
+			var task = new FutureTask<>(() -> getAttachmentFileContent(request, pipedOutputStream), null);
+
+			executor.execute(task);
 			sendFileContent(pipedInputStream, responseObserver);
+			handleExceptionOnRetrievingContent(task);
+
 		} catch (IOException e) {
 			throw new TechnicalException("Error on sending attachment content!", e);
 		}
 	}
 
 	void getAttachmentFileContent(GrpcGetAttachmentContentRequest request, PipedOutputStream pipedOutputStream) {
-		new Thread(() -> service.getAttachmentContent(attachmentFileRequestMapper.fromGrpcContentRequest(request), pipedOutputStream))
-				.start();
+		service.getAttachmentContent(attachmentFileRequestMapper.fromGrpcContentRequest(request), pipedOutputStream);
 	}
 
 	void sendFileContent(InputStream fileContent, StreamObserver<GrpcGetAttachmentContentResponse> responseObserver) {
@@ -174,6 +183,22 @@ class AntragraumGrpcService extends AntragraumServiceGrpc.AntragraumServiceImplB
 		throw new TechnicalException(message, e);
 	}
 
+	void handleExceptionOnRetrievingContent(FutureTask<Object> task) {
+		try {
+			task.get();
+		} catch (InterruptedException e) { // NOSONAR
+			throw new TechnicalException("Retrieving attachment content was interupted.", e);
+		} catch (ExecutionException e) {
+			if (e.getCause() instanceof SecurityException) {
+				throw (SecurityException) e.getCause();
+			}
+			if (e.getCause() instanceof NotFoundException) {
+				throw (NotFoundException) e.getCause();
+			}
+			throw new TechnicalException("Error on retrieving attachment content.", e);
+		}
+	}
+
 	@Override
 	public void getAttachmentMetadata(GrpcGetAttachmentMetadataRequest request, StreamObserver<GrpcGetAttachmentMetadataResponse> responseObserver) {
 		var attachment = service.getAttachmentMetadata(attachmentFileRequestMapper.fromGrpcMetadataRequest(request));
diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java
index 1d37a4c1baf60cf62359cdd322f615fb469c2d4c..6e99cae1ca29f0bf7b6298719a5eee7d70661826 100644
--- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java
+++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java
@@ -36,6 +36,10 @@ import java.time.temporal.ChronoUnit;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
 import java.util.stream.Stream;
 
 import org.apache.commons.io.IOUtils;
@@ -53,9 +57,12 @@ import org.mockito.MockedStatic;
 import org.mockito.Spy;
 
 import com.google.protobuf.ByteString;
+import com.thedeanda.lorem.LoremIpsum;
 
+import de.ozgcloud.apilib.common.errorhandling.NotFoundException;
 import de.ozgcloud.apilib.file.OzgCloudFile;
 import de.ozgcloud.apilib.file.OzgCloudFileTestFactory;
+import de.ozgcloud.common.datatype.StringBasedValue;
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory;
 import de.ozgcloud.nachrichten.common.vorgang.Vorgang;
@@ -486,6 +493,14 @@ class AntragraumGrpcServiceTest {
 			private MockedConstruction<PipedOutputStream> mockedConstructionOutput;
 			private InputStream connectedInput;
 
+			private MockedConstruction<FutureTask> mockedConstructionFutureTask; // NOSONAR
+			private FutureTask<Object> futureTask;
+			private Runnable runnable;
+
+			private MockedStatic<Executors> mockedStaticExecutors;
+			@Mock
+			private ExecutorService executor;
+
 			@BeforeEach
 			void setUpMockedConstruction() {
 				mockedConstructionInput = mockConstruction(PipedInputStream.class, (pipedInputStream, context) -> {
@@ -496,12 +511,20 @@ class AntragraumGrpcServiceTest {
 					this.pipedOutputStream = pipedOutputStream;
 					connectedInput = (InputStream) context.arguments().get(0);
 				});
+				mockedConstructionFutureTask = mockConstruction(FutureTask.class, (futureTask, context) -> {
+					this.futureTask = futureTask; // NOSONAR
+					runnable = (Runnable) context.arguments().get(0);
+				});
+				mockedStaticExecutors = mockStatic(Executors.class);
+				mockedStaticExecutors.when(() -> Executors.newFixedThreadPool(1)).thenReturn(executor);
 			}
 
 			@AfterEach
 			void closeMocks() {
 				mockedConstructionInput.close();
 				mockedConstructionOutput.close();
+				mockedConstructionFutureTask.close();
+				mockedStaticExecutors.close();
 			}
 
 			@Test
@@ -526,10 +549,24 @@ class AntragraumGrpcServiceTest {
 			}
 
 			@Test
-			void shouldCallGetAttachmentFileContent() {
+			void shouldCreateNewFixedThreadPool() {
+				callGetAttachmentContent();
+
+				mockedStaticExecutors.verify(() -> Executors.newFixedThreadPool(1));
+			}
+
+			@Test
+			void shouldConstructFutureTask() {
+				callGetAttachmentContent();
+
+				assertThat(mockedConstructionFutureTask.constructed()).hasSize(1);
+			}
+
+			@Test
+			void shouldExecuteTask() {
 				callGetAttachmentContent();
 
-				verify(grpcService).getAttachmentFileContent(grpcRequest, pipedOutputStream);
+				verify(executor).execute(futureTask);
 			}
 
 			@Test
@@ -538,6 +575,25 @@ class AntragraumGrpcServiceTest {
 
 				verify(grpcService).sendFileContent(pipedInputStream, responseObserver);
 			}
+
+			@Test
+			void shouldCallHandleExceptionOnRetrievingContent() {
+				callGetAttachmentContent();
+
+				verify(grpcService).handleExceptionOnRetrievingContent(futureTask);
+			}
+
+			@Nested
+			class TestTask {
+				@Test
+				void shouldCallGetAttachmentFileContent() {
+					callGetAttachmentContent();
+
+					runnable.run();
+
+					verify(grpcService).getAttachmentFileContent(grpcRequest, pipedOutputStream);
+				}
+			}
 		}
 
 		@Nested
@@ -579,65 +635,26 @@ class AntragraumGrpcServiceTest {
 		@Mock
 		private PipedOutputStream pipedOutputStream;
 
-		private MockedConstruction<Thread> mockedConstructionThread;
-		private Runnable passedRunnable;
-		private Thread thread;
-
 		private final GrpcGetAttachmentContentRequest grpcRequest = GrpcGetAttachmentContentRequestTestFactory.create();
 		private final AttachmentFileRequest request = AttachmentFileRequestTestFactory.create();
 
 		@BeforeEach
 		void mock() {
-			mockedConstructionThread = mockConstruction(Thread.class, (mock, context) -> {
-				passedRunnable = (Runnable) context.arguments().get(0);
-				thread = mock;
-			});
-		}
-
-		@AfterEach
-		void closeMock() {
-			mockedConstructionThread.close();
+			when(attachmentFileRequestMapper.fromGrpcContentRequest(grpcRequest)).thenReturn(request);
 		}
 
 		@Test
-		void shouldConstructNewThread() {
+		void shouldMapRequest() {
 			callGetRueckfrageAttachmentFile();
 
-			assertThat(mockedConstructionThread.constructed()).hasSize(1);
+			verify(attachmentFileRequestMapper).fromGrpcContentRequest(grpcRequest);
 		}
 
 		@Test
-		void shouldStartThread() {
+		void shouldCallServiceToGetAttachmentContent() {
 			callGetRueckfrageAttachmentFile();
 
-			verify(thread).start();
-		}
-
-		@Nested
-		class TestRunnable {
-			@BeforeEach
-			void mock() {
-				when(attachmentFileRequestMapper.fromGrpcContentRequest(grpcRequest)).thenReturn(request);
-			}
-
-			@Test
-			void shouldMapRequest() {
-				callGetRueckfrageAttachmentFile();
-
-				passedRunnable.run();
-
-				verify(attachmentFileRequestMapper).fromGrpcContentRequest(grpcRequest);
-			}
-
-			@Test
-			void shouldCallServiceToGetAttachmentContent() {
-				callGetRueckfrageAttachmentFile();
-
-				passedRunnable.run();
-
-				verify(service).getAttachmentContent(request, pipedOutputStream);
-			}
-
+			verify(service).getAttachmentContent(request, pipedOutputStream);
 		}
 
 		private void callGetRueckfrageAttachmentFile() {
@@ -818,6 +835,71 @@ class AntragraumGrpcServiceTest {
 
 	}
 
+	@Nested
+	class TestHandleExceptionOnRetrievingContent {
+
+		@Mock
+		private FutureTask<Object> futureTask;
+
+		private final StringBasedValue id = new StringBasedValue() {
+		};
+		private final String entityName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		@SneakyThrows
+		void shouldGettaskResult() {
+			callHandleExceptionOnRetrievingContent();
+
+			verify(futureTask).get();
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldThrowTechnicalExceptionOnInteruption() {
+			var interruptedException = new InterruptedException();
+			when(futureTask.get()).thenThrow(interruptedException);
+
+			assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent())
+					.isInstanceOf(TechnicalException.class)
+					.hasCause(interruptedException);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldRethrowSecurityException() {
+			var securityException = new SecurityException();
+			when(futureTask.get()).thenThrow(new ExecutionException(securityException));
+
+			assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent())
+					.isInstanceOf(SecurityException.class);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldRethrowNotFoundException() {
+			var notFoundException = new NotFoundException(id, entityName);
+			when(futureTask.get()).thenThrow(new ExecutionException(notFoundException));
+
+			assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent())
+					.isInstanceOf(NotFoundException.class);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldThrowTechnicalExceptionOtherExecutionException() {
+			var executionException = new ExecutionException(new Exception());
+			when(futureTask.get()).thenThrow(executionException);
+
+			assertThatThrownBy(() -> callHandleExceptionOnRetrievingContent())
+					.isInstanceOf(TechnicalException.class)
+					.hasCause(executionException);
+		}
+
+		private void callHandleExceptionOnRetrievingContent() {
+			grpcService.handleExceptionOnRetrievingContent(futureTask);
+		}
+	}
+
 	@Nested
 	class TestGetAttachmentMetadata {