diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
index a9fa9e550582efd27f8840b3cae3d33f86ee3395..a9f57bac1d65ca9aba3af9671ab6d2efb2948558 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
@@ -35,6 +35,7 @@ import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.FindAndModifyOptions;
 import org.springframework.data.mongodb.core.MongoOperations;
@@ -49,8 +50,6 @@ import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.data.mongodb.core.query.UpdateDefinition;
 import org.springframework.stereotype.Repository;
 
-import com.google.common.collect.ObjectArrays;
-
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.CommandStatus;
 
@@ -58,7 +57,8 @@ import de.ozgcloud.command.CommandStatus;
 class CommandRepository {
 
 	private static final String MONGODB_ID = "id";
-	private static final String MONGODB_STATUS = "status";
+	static final String MONGODB_STATUS = "status";
+	private static final String MONGODB_REFERENCE_STATUS = "$status";
 	private static final String MONGODB_FINISHED_AT = "finishedAt";
 	private static final String MONGODB_RELATION_VERSION = "relationVersion";
 	private static final String MONGODB_ERROR_MSG = "errorMessage";
@@ -108,6 +108,10 @@ class CommandRepository {
 				Command.class);
 	}
 
+	public Command updateCommandStatusAndReturnPrevious(String commandId, CommandStatus status) {
+		return mongoOperations.findAndModify(queryById(commandId), new Update().set(MONGODB_STATUS, status), Command.class);
+	}
+
 	void setErrorMessage(String commandId, String errorMsg) {
 		mongoOperations.updateFirst(queryById(commandId),
 				new Update()
@@ -202,12 +206,9 @@ class CommandRepository {
 		mongoOperations.updateFirst(queryById(commandId), update, Command.class);
 	}
 
-	public Optional<String> getNotFailedParentId(String commandId) {
-		return getParentId(commandId)
-				.map(this::queryNotFailedCommandById)
-				.map(this::includeIdAndClass)
-				.flatMap(this::findOne)
-				.map(Command::getId);
+	public boolean isCommandFailed(String commandId) {
+		return mongoOperations.exists(query(new Criteria().andOperator(criteriaById(commandId), where(MONGODB_STATUS).is(CommandStatus.ERROR))),
+				Command.class);
 	}
 
 	public Optional<String> getParentId(String commandId) {
@@ -224,12 +225,6 @@ class CommandRepository {
 		return MapUtils.getString(body, PersistedCommand.PROPERTY_PARENT_ID);
 	}
 
-	Query queryNotFailedCommandById(String commandId) {
-		return query(new Criteria().andOperator(
-				where(MONGODB_ID).is(commandId),
-				where(MONGODB_STATUS).ne(CommandStatus.ERROR)));
-	}
-
 	Optional<Command> findOne(Query query) {
 		return Optional.ofNullable(mongoOperations.findOne(query, Command.class));
 	}
@@ -246,17 +241,21 @@ class CommandRepository {
 		return mongoOperations.exists(buildQueryNotInStatus(parentId, CommandStatus.FINISHED, CommandStatus.REVOKED), Command.class);
 	}
 
-	public Stream<String> findNotFailedSubCommandIds(String parentId) {
-		return mongoOperations.stream(includeIdAndClass(buildQueryNotInStatus(parentId, CommandStatus.ERROR)), Command.class).map(Command::getId);
-	}
-
-	private Query buildQueryNotInStatus(String parentId, CommandStatus status, CommandStatus... statuses) {
-		Object[] excludeStatuses = ObjectArrays.concat(status, statuses);
+	Query buildQueryNotInStatus(String parentId, CommandStatus status, CommandStatus... statuses) {
+		Object[] excludeStatuses = ArrayUtils.add(statuses, status);
 		return query(new Criteria().andOperator(
-				where(MONGODB_PARENT_ID).is(parentId),
+				buildIsParentIdCriteria(parentId),
 				where(MONGODB_STATUS).nin(excludeStatuses)));
 	}
 
+	public Stream<String> findSubCommandIds(String parentId) {
+		return mongoOperations.stream(includeIdAndClass(query(buildIsParentIdCriteria(parentId))), Command.class).map(Command::getId);
+	}
+
+	private Criteria buildIsParentIdCriteria(String parentId) {
+		return where(MONGODB_PARENT_ID).is(parentId);
+	}
+
 	Query includeIdAndClass(Query query) {
 		query.fields().include(MONGODB_CLASS, MONGODB_ID);
 		return query;
@@ -266,16 +265,30 @@ class CommandRepository {
 		return mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevoke(), FindAndModifyOptions.options().returnNew(true), Command.class);
 	}
 
+	private UpdateDefinition buildUpdateStatusRevoke() {
+		var switchOperation = Switch.switchCases(
+				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.NEW)).then(CommandStatus.CANCELED),
+				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.PENDING)).then(CommandStatus.REVOKE_PENDING),
+				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING))
+				.defaultTo(MONGODB_REFERENCE_STATUS);
+		return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(switchOperation));
+	}
+
+	public Optional<Command> setRevokeStatusIfNotPending(String id) {
+		var updateCommand = mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevokeIfNotPending(),
+				FindAndModifyOptions.options().returnNew(true), Command.class);
+		return Optional.ofNullable(updateCommand);
+	}
+
 	private Query queryById(String commandId) {
 		return query(criteriaById(commandId));
 	}
 
-	private UpdateDefinition buildUpdateStatusRevoke() {
+	private UpdateDefinition buildUpdateStatusRevokeIfNotPending() {
 		var switchOperation = Switch.switchCases(
 				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.NEW)).then(CommandStatus.CANCELED),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.PENDING)).then(CommandStatus.REVOKE_PENDING),
-				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING))
-				.defaultTo("$status");
+				CaseOperator.when(Eq.valueOf(MONGODB_STATUS).equalToValue(CommandStatus.FINISHED)).then(CommandStatus.REVOKE_PENDING)
+		).defaultTo(MONGODB_REFERENCE_STATUS);
 		return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(switchOperation));
 	}
 
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
index d8db39506c8338dbebe21a79985a5d3f7cfccfb1..2f661a37b47f0da8143fdd5332e8385da4ecb1e5 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
@@ -24,7 +24,6 @@
 package de.ozgcloud.vorgang.command;
 
 import static de.ozgcloud.vorgang.command.PersistedCommand.*;
-import static java.util.Objects.*;
 
 import java.time.ZonedDateTime;
 import java.util.Collection;
@@ -34,10 +33,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
-import java.util.function.Consumer;
 import java.util.stream.Stream;
 
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.collections4.MapUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
@@ -55,6 +53,7 @@ import de.ozgcloud.vorgang.callcontext.CallContextUser;
 import de.ozgcloud.vorgang.callcontext.CurrentUserService;
 import de.ozgcloud.vorgang.callcontext.User;
 import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.common.errorhandling.RevokeFailedException;
 import lombok.NonNull;
 
 @Service
@@ -117,52 +116,85 @@ public class CommandService {
 
 	public void setCommandFinished(String commandId, String createdResource) {
 		var command = getById(commandId);
-		if (command.getStatus() == CommandStatus.REVOKE_PENDING) {
+		if (shouldRevoke(command)) {
+			repository.setRevokeStatus(commandId);
 			publishRevokeCommandEvent(command);
 			return;
 		}
-		Optional.ofNullable(createdResource).ifPresentOrElse(
-				resource -> repository.finishCommand(commandId, resource),
+		Optional.ofNullable(createdResource).ifPresentOrElse(resource -> repository.finishCommand(commandId, resource),
 				() -> repository.finishCommand(commandId));
-		getCompletableParentId(commandId).filter(parentId -> !repository.existsNotFinishedSubCommands(parentId))
-				.ifPresent(this::publishCommandExecutedEvent);
+		getCompletableParentId(command).ifPresent(this::publishCommandExecutedEvent);
 	}
 
-	Optional<String> getCompletableParentId(String commandId) {
-		return repository.getParentId(commandId).filter(repository::isCompleteIfSubsCompleted);
+	boolean shouldRevoke(Command command) {
+		return command.getStatus() == CommandStatus.REVOKE_PENDING || isParentCommandFailed(command);
+	}
+
+	boolean isParentCommandFailed(Command command) {
+		return getParentId(command).filter(repository::isCommandFailed).isPresent();
+	}
+
+	Optional<String> getCompletableParentId(Command command) {
+		return getParentId(command).filter(repository::isCompleteIfSubsCompleted)
+				.filter(parentId -> !repository.existsNotFinishedSubCommands(parentId));
+	}
+
+	Optional<String> getParentId(Command command) {
+		return Optional.ofNullable(command.getBodyObject()).map(body -> MapUtils.getString(body, PROPERTY_PARENT_ID));
 	}
 
 	public void publishCommandExecutedEvent(String commandId) {
 		findById(commandId).ifPresent(command -> publisher.publishEvent(new CommandExecutedEvent(command)));
 	}
 
-	public void setCommandError(String id, String errorMessage) {
-		repository.setErrorMessage(id, errorMessage);
-		var publishCommandFailedEvent = createCommandFailedEventPublisher("Command %s failed: %s".formatted(id, errorMessage));
-		repository.findNotFailedSubCommandIds(id).filter(notFailedCommandId -> !StringUtils.equals(notFailedCommandId, id))
-				.forEach(publishCommandFailedEvent);
-		repository.getNotFailedParentId(id).ifPresent(publishCommandFailedEvent);
+	public void setCommandError(String commandId, String errorMessage) {
+		repository.setErrorMessage(commandId, errorMessage);
+		repository.getParentId(commandId).map(this::setErrorStatus).filter(this::notErrorStatus)
+				.map(Command::getId).ifPresent(parentId -> handleCommandError(commandId, parentId));
+	}
+
+	Command setErrorStatus(String commandId) {
+		return Optional.ofNullable(repository.updateCommandStatusAndReturnPrevious(commandId, CommandStatus.ERROR))
+				.orElseThrow(() -> new NotFoundException(Command.class, commandId));
 	}
 
-	Consumer<String> createCommandFailedEventPublisher(String errorMessage) {
-		return commandId -> publisher.publishEvent(new CommandFailedEvent(commandId, errorMessage));
+	boolean notErrorStatus(Command command) {
+		return command.getStatus() != CommandStatus.ERROR;
+	}
+
+	void handleCommandError(String commandId, String parentId) {
+		publishCommandFailedEvent(parentId, "Command %s failed because subcommand %s failed".formatted(parentId, commandId));
+		revokeSubCommands(parentId);
+	}
+
+	void publishCommandFailedEvent(String commandId, String errorMessage) {
+		publisher.publishEvent(new CommandFailedEvent(commandId, errorMessage));
+	}
+
+	void revokeSubCommands(String parentId) {
+		repository.findSubCommandIds(parentId).forEach(this::revokeCommandSilent);
 	}
 
 	public void setCommandRevoked(String commandId) {
 		repository.updateCommandStatus(commandId, CommandStatus.REVOKED);
 	}
 
-	public Command revokeCommand(final String commandId) {
-		var updatedCommand = setRevokeStatus(commandId);
-		if (isNull(updatedCommand)) {
-			throw new NotFoundException(Command.class, commandId);
+	public Command revokeCommand(String commandId) {
+		var updatedCommand = revokeCommandSilent(commandId).orElseThrow(() -> new NotFoundException(Command.class, commandId));
+		if (!isRevokePending(updatedCommand)) {
+			throw new RevokeFailedException(commandId, "Unexpected status '%s'. (expected: REVOKE_PENDING)".formatted(updatedCommand.getStatus()));
 		}
-		publishRevokeCommandEvent(updatedCommand);
 		return updatedCommand;
 	}
 
-	public Command setRevokeStatus(String commandId) {
-		return repository.setRevokeStatus(commandId);
+	Optional<Command> revokeCommandSilent(String commandId) {
+		var updatedCommand = repository.setRevokeStatusIfNotPending(commandId);
+		updatedCommand.filter(this::isRevokePending).ifPresent(this::publishRevokeCommandEvent);
+		return updatedCommand;
+	}
+
+	boolean isRevokePending(Command command) {
+		return command.getStatus() == CommandStatus.REVOKE_PENDING;
 	}
 
 	void publishRevokeCommandEvent(Command command) {
@@ -194,16 +226,16 @@ public class CommandService {
 	}
 
 	public Stream<Command> createSubCommands(CreateSubCommandsRequest request) {
-		var parentCommand = getNotFailedCommand(request.getParentId());
+		var parentCommand = getPendingCommand(request.getParentId());
 		repository.addSubCommands(parentCommand.getId(), buildSubCommandValues(request));
 		return request.getSubCommands().stream().map(subCommand -> buildCreateCommandRequest(subCommand, parentCommand))
 				.map(this::createCommand);
 	}
 
-	Command getNotFailedCommand(String commandId) {
+	Command getPendingCommand(String commandId) {
 		var command = getById(commandId);
-		if (command.getStatus() == CommandStatus.ERROR) {
-			throw new TechnicalException("Cannot add sub commands to failed command ('%s')".formatted(commandId));
+		if (command.getStatus() != CommandStatus.PENDING) {
+			throw new TechnicalException("Cannot add sub commands to command '%s'. Parent command must have status PENDING".formatted(commandId));
 		}
 		return command;
 	}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/RevokeFailedException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/RevokeFailedException.java
new file mode 100644
index 0000000000000000000000000000000000000000..133b8970b815aaf02ad3284a24babd821ea13b0a
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/RevokeFailedException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.errorhandling;
+
+import java.util.Map;
+
+import de.ozgcloud.common.errorhandling.FunctionalErrorCode;
+
+public class RevokeFailedException extends FunctionalException {
+
+	static final String KEY_COMMAND_ID = "Id";
+
+	private static final String MESSAGE_TEMPLATE = "Can not revoke command with id '%s'. %s";
+	private static final FunctionalErrorCode ERROR_CODE = () -> "error.revoke_failed";
+
+	public RevokeFailedException(String commandId, String message) {
+		super(MESSAGE_TEMPLATE.formatted(commandId, message), ERROR_CODE, Map.of(KEY_COMMAND_ID, commandId));
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java
index 90a0fda17c0b5223d9e2745acfb09dc8cc8ece93..cbb89a295b4dde09f94322dc54cad4cf97f7c172 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java
@@ -309,7 +309,7 @@ class CommandITCase {
 				mongoOperations.dropCollection(Vorgang.class);
 				mongoOperations.save(VorgangTestFactory.createBuilder().status(Status.ANGENOMMEN).build());
 
-				mongoOperations.save(CommandTestFactory.createBuilder()
+				mongoOperations.save(CommandTestFactory.createBuilder().status(CommandStatus.FINISHED)
 						.relationId(VorgangTestFactory.ID).relationVersion(VorgangTestFactory.VERSION - 1)
 						.previousState(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.NEU)).build());
 			}
@@ -369,7 +369,7 @@ class CommandITCase {
 			void persistVorgangWithVorgangVerwerfenCommand() {
 				mongoOperations.save(VorgangTestFactory.createBuilder().status(Status.VERWORFEN).build());
 
-				mongoOperations.save(CommandTestFactory.createBuilder().relationId(VorgangTestFactory.ID)
+				mongoOperations.save(CommandTestFactory.createBuilder().status(CommandStatus.FINISHED).relationId(VorgangTestFactory.ID)
 						.relationVersion(VorgangTestFactory.VERSION - 1).order(Order.VORGANG_VERWERFEN.toString())
 						.previousState(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.IN_BEARBEITUNG))
 						.build());
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
index a5ad4922d9ac97cd7dff429a2a0634f280f4313d..6f99e9b91bef7f1664e80194b2755173a0c1da37 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
@@ -246,6 +246,31 @@ class CommandRepositoryITCase {
 		}
 	}
 
+	@Nested
+	class TestUpdateCommandStatusAndReturnPrevious {
+
+		@BeforeEach
+		void persistVorgangWithCommand() {
+			repository.save(CommandTestFactory.create());
+		}
+
+		@Test
+		void shouldUpdateStatus() {
+			repository.updateCommandStatusAndReturnPrevious(CommandTestFactory.ID, CommandStatus.ERROR);
+
+			var command = mongoOperations.findById(CommandTestFactory.ID, Command.class);
+			assertThat(command.getStatus()).isEqualTo(CommandStatus.ERROR);
+		}
+
+		@Test
+		void shouldReturnPreviousCommand() {
+			Command previousCommand = repository.updateCommandStatusAndReturnPrevious(CommandTestFactory.ID, CommandStatus.ERROR);
+
+			assertThat(previousCommand.getStatus()).isEqualTo(CommandStatus.PENDING);
+		}
+
+	}
+
 	@Nested
 	class TestGetPendingCommands {
 
@@ -417,7 +442,7 @@ class CommandRepositoryITCase {
 	}
 
 	@Nested
-	class TestGetNotFailedParentId {
+	class TestIsCommandFailed {
 
 		@BeforeEach
 		void init() {
@@ -426,28 +451,22 @@ class CommandRepositoryITCase {
 
 		@Test
 		void shouldReturnParentId() {
-			var parentId = mongoOperations.save(CommandTestFactory.createBuilder().bodyObject(Map.of(
+			var commandId = mongoOperations.save(CommandTestFactory.createBuilder().bodyObject(Map.of(
 					PersistedCommand.PROPERTY_COMPLETE_IF_SUBS_COMPLETED, true)).build()).getId();
-			var commandId = mongoOperations.save(
-					CommandTestFactory.createBuilder().id(null).bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, parentId)).build())
-					.getId();
 
-			var result = repository.getNotFailedParentId(commandId);
+			var result = repository.isCommandFailed(commandId);
 
-			assertThat(result).contains(parentId);
+			assertThat(result).isFalse();
 		}
 
 		@Test
 		void shouldReturnEmpty() {
-			var parentId = mongoOperations.save(CommandTestFactory.createBuilder().status(CommandStatus.ERROR).bodyObject(Map.of(
+			var commandId = mongoOperations.save(CommandTestFactory.createBuilder().status(CommandStatus.ERROR).bodyObject(Map.of(
 					PersistedCommand.PROPERTY_COMPLETE_IF_SUBS_COMPLETED, true)).build()).getId();
-			var commandId = mongoOperations.save(
-					CommandTestFactory.createBuilder().id(null).bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, parentId)).build())
-					.getId();
 
-			var result = repository.getNotFailedParentId(commandId);
+			var result = repository.isCommandFailed(commandId);
 
-			assertThat(result).isEmpty();
+			assertThat(result).isTrue();
 		}
 	}
 
@@ -562,8 +581,8 @@ class CommandRepositoryITCase {
 
 		private static final String PARENT_ID = "parent-id";
 
-		private final PersistedCommandBuilder commandWithParentIdBuilder = CommandTestFactory.createBuilder().id(null).bodyObject(Map.of(
-				PersistedCommand.PROPERTY_PARENT_ID, PARENT_ID));
+		private static final Command COMMAND_WITH_PARENT_ID = CommandTestFactory.createBuilder().id(null).bodyObject(Map.of(
+				PersistedCommand.PROPERTY_PARENT_ID, PARENT_ID)).build();
 
 		@BeforeEach
 		void init() {
@@ -571,30 +590,19 @@ class CommandRepositoryITCase {
 		}
 
 		@Test
-		void shouldIgnoreErrorStatus() {
-			mongoOperations.save(commandWithParentIdBuilder.status(CommandStatus.ERROR).build());
+		void shouldFindSubCommandIds() {
+			var commandId = mongoOperations.save(COMMAND_WITH_PARENT_ID).getId();
 
-			var result = repository.findNotFailedSubCommandIds(PARENT_ID);
+			var result = repository.findSubCommandIds(PARENT_ID);
 
-			assertThat(result).isEmpty();
-		}
-
-		@DisplayName("should find commands")
-		@ParameterizedTest(name = "with status {0}")
-		@EnumSource(value = CommandStatus.class, names = { "ERROR" }, mode = EnumSource.Mode.EXCLUDE)
-		void shouldFindCommands(CommandStatus status) {
-			mongoOperations.save(commandWithParentIdBuilder.status(status).build());
-
-			var result = repository.findNotFailedSubCommandIds(PARENT_ID);
-
-			assertThat(result).hasSize(1);
+			assertThat(result).hasSize(1).first().isEqualTo(commandId);
 		}
 
 		@Test
 		void shouldReturnEmpty() {
-			mongoOperations.save(commandWithParentIdBuilder.build());
+			mongoOperations.save(COMMAND_WITH_PARENT_ID);
 
-			var result = repository.findNotFailedSubCommandIds("other-parent-id");
+			var result = repository.findSubCommandIds("other-parent-id");
 
 			assertThat(result).isEmpty();
 		}
@@ -645,4 +653,45 @@ class CommandRepositoryITCase {
 			assertThat(result).isPresent().get().extracting(Command::getStatus).isEqualTo(status);
 		}
 	}
+
+	@Nested
+	class TestSetRevokeStatusIfNotPending {
+
+		@Test
+		void shouldSetCanceled() {
+			var command = createCommand(CommandStatus.NEW);
+
+			repository.setRevokeStatusIfNotPending(command.getId());
+
+			assertThat(getCommandStatus(command)).isEqualTo(CommandStatus.CANCELED);
+		}
+
+		@Test
+		void shouldSetRevokePendingWhenFinished() {
+			var command = createCommand(CommandStatus.FINISHED);
+
+			repository.setRevokeStatusIfNotPending(command.getId());
+
+			assertThat(getCommandStatus(command)).isEqualTo(CommandStatus.REVOKE_PENDING);
+		}
+
+		@DisplayName("should not update when")
+		@ParameterizedTest(name = "status is {0}")
+		@EnumSource(value = CommandStatus.class, names = { "NEW", "FINISHED" }, mode = EnumSource.Mode.EXCLUDE)
+		void shouldNotUpdate(CommandStatus status) {
+			var command = createCommand(status);
+
+			repository.setRevokeStatusIfNotPending(command.getId());
+
+			assertThat(getCommandStatus(command)).isEqualTo(status);
+		}
+
+		private Command createCommand(CommandStatus status) {
+			return mongoOperations.save(CommandTestFactory.createBuilder().id(null).status(status).build());
+		}
+
+		private CommandStatus getCommandStatus(Command command) {
+			return mongoOperations.findById(command.getId(), Command.class).getStatus();
+		}
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
index 4e0eb1bf86891204eae2eaeec75a9dc8689e2649..36429601be30bae6182023940b10249ba1bd6a6f 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
@@ -28,6 +28,7 @@ import static org.awaitility.Awaitility.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
@@ -115,12 +116,14 @@ class CommandServiceITCase {
 	@Nested
 	class TestVorgangCommandFinished {
 
+		private Vorgang vorgang;
+
 		@BeforeEach
 		void persistVorgang() {
 			mongoOperations.dropCollection(Vorgang.class);
 			mongoOperations.dropCollection(Command.class);
 
-			mongoOperations.save(VorgangTestFactory.create());
+			vorgang = mongoOperations.save(VorgangTestFactory.create());
 			mongoOperations.save(CommandTestFactory.createBuilder().relationId(VorgangTestFactory.ID).build());
 		}
 
@@ -136,6 +139,37 @@ class CommandServiceITCase {
 			assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
 			assertThat(command.getRelationId()).isEqualTo(VorgangTestFactory.ID);
 		}
+
+		@Test
+		void shouldRevokeFinishedCommand() {
+			var commandId = saveSubCommandWithFailedParent();
+
+			commandService.setCommandFinished(commandId);
+
+			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> {
+				var commandStatus = mongoOperations.findById(commandId, Command.class).getStatus();
+				assertThat(commandStatus).isEqualTo(CommandStatus.REVOKED);
+			});
+		}
+
+		private String saveSubCommandWithFailedParent() {
+			var parentId = mongoOperations.save(createFailedParentCommand()).getId();
+			return mongoOperations.save(createSubCommand(parentId)).getId();
+		}
+
+		private Command createFailedParentCommand() {
+			return CommandTestFactory.createBuilder().id(null).status(CommandStatus.ERROR)
+					.bodyObject(Map.of(
+							PersistedCommand.PROPERTY_EXECUTION_MODE, SubCommandExecutionMode.PARALLEL.name(),
+							PersistedCommand.PROPERTY_COMPLETE_IF_SUBS_COMPLETED, true
+					)).build();
+		}
+
+		private Command createSubCommand(String parentId) {
+			return CommandTestFactory.createBuilder().id(null).vorgangId(vorgang.getId())
+					.previousState(Map.of(CommandRepository.MONGODB_STATUS, Vorgang.Status.NEU.name()))
+					.bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, parentId)).build();
+		}
 	}
 
 	@Nested
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
index 04b5e6f9dfb000b85d9685a792608d81625583b5..85714d30f81e92ba77ce0c7f575e89dcc04343fa 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
@@ -39,6 +39,8 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
@@ -48,7 +50,6 @@ import org.springframework.context.ApplicationEventPublisher;
 
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.CommandExecutedEvent;
-import de.ozgcloud.command.CommandFailedEvent;
 import de.ozgcloud.command.CommandStatus;
 import de.ozgcloud.command.RevokeCommandEvent;
 import de.ozgcloud.common.errorhandling.TechnicalException;
@@ -57,6 +58,7 @@ import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
 import de.ozgcloud.vorgang.callcontext.CurrentUserService;
 import de.ozgcloud.vorgang.callcontext.UserTestFactory;
 import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.common.errorhandling.RevokeFailedException;
 import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class CommandServiceTest {
@@ -210,53 +212,73 @@ class CommandServiceTest {
 		}
 
 		@Nested
-		class TestRevokeCommand {
+		class TestRevokePendingCommand {
 
-			private Command command;
+			private static final Command REVOKE_PENDING_COMMAND = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build();
 
 			@BeforeEach
 			void init() {
-				command = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build();
-				doReturn(command).when(service).getById(anyString());
+				doReturn(true).when(service).shouldRevoke(any());
+				doReturn(REVOKE_PENDING_COMMAND).when(service).getById(anyString());
+			}
+
+			@Test
+			void shouldCallIsRevokeCommand() {
+				setCommandFinished();
+
+				verify(service).shouldRevoke(REVOKE_PENDING_COMMAND);
+			}
+
+			@Test
+			void shouldCallRepository() {
+				setCommandFinished();
+
+				verify(repository).setRevokeStatus(CommandTestFactory.ID);
 			}
 
 			@Test
 			void shouldCallPublishRevokeCommandEvent() {
-				service.setCommandFinished(CommandTestFactory.ID);
+				setCommandFinished();
 
-				verify(service).publishRevokeCommandEvent(command);
+				verify(service).publishRevokeCommandEvent(REVOKE_PENDING_COMMAND);
 			}
 
 			@Test
 			void shouldNotCallFinishCommandIfRevokePending() {
-				service.setCommandFinished(CommandTestFactory.ID);
+				setCommandFinished();
 
 				verify(repository, never()).finishCommand(anyString());
 				verify(repository, never()).finishCommand(anyString(), anyString());
 			}
 
+			void setCommandFinished() {
+				service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+			}
 		}
 
 		@Nested
 		class TestFinishCommand {
 
+			private static final Command FINISHED_COMMAND = CommandTestFactory.createBuilder().status(CommandStatus.FINISHED).build();
+
 			@BeforeEach
 			void init() {
-				doReturn(CommandTestFactory.create()).when(service).getById(anyString());
+				doReturn(false).when(service).isParentCommandFailed(any());
+				doReturn(FINISHED_COMMAND).when(service).getById(anyString());
 			}
 
 			@Test
-			void shouldCallGetCommand() {
+			void shouldCallSetCommandFinish() {
 				service.setCommandFinished(CommandTestFactory.ID);
 
-				verify(service).getById(CommandTestFactory.ID);
+				verify(service).setCommandFinished(CommandTestFactory.ID, null);
 			}
 
 			@Test
-			void shouldCallFinishCommand() {
-				service.setCommandFinished(CommandTestFactory.ID);
+			void shouldCallGetCommand() {
+				setCommandFinished();
 
-				verify(service).setCommandFinished(CommandTestFactory.ID, null);
+				verify(service).getById(CommandTestFactory.ID);
 			}
 
 			@Test
@@ -268,105 +290,219 @@ class CommandServiceTest {
 
 			@Test
 			void shouldCallRepositoryFinishCommandWithCreatedResource() {
-				service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+				setCommandFinished();
 
 				verify(repository).finishCommand(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
 			}
 
 			@Test
 			void shouldCallGetCompletableParentId() {
-				service.setCommandFinished(CommandTestFactory.ID);
+				setCommandFinished();
 
-				verify(service).getCompletableParentId(CommandTestFactory.ID);
+				verify(service).getCompletableParentId(FINISHED_COMMAND);
 			}
 
 			@Test
-			void shouldCallExistsNotFinishedSubCommands() {
+			void shouldCallPublishCommandExecutedEvent() {
 				var parentId = "parent-id";
 				doReturn(Optional.of(parentId)).when(service).getCompletableParentId(any());
 
-				service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+				setCommandFinished();
 
-				verify(repository).existsNotFinishedSubCommands(parentId);
+				verify(service).publishCommandExecutedEvent(parentId);
 			}
 
+			@DisplayName("should not call publishCommandExecutedEvent when no completable parent id")
 			@Test
-			void shouldCallPublishCommandExecutedEvent() {
-				var parentId = "parent-id";
-				doReturn(Optional.of(parentId)).when(service).getCompletableParentId(any());
+			void shouldNotPublishWhenNoParentId() {
+				doReturn(Optional.empty()).when(service).getCompletableParentId(any());
+
+				setCommandFinished();
 
+				verify(service, never()).publishCommandExecutedEvent(anyString());
+			}
+
+			void setCommandFinished() {
 				service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+			}
+		}
+	}
 
-				verify(service).publishCommandExecutedEvent(parentId);
+	@Nested
+	class TestShouldRevoke {
+
+		@Test
+		void shouldReturnTrueWhenRevokePending() {
+			var command = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build();
+
+			var result = service.shouldRevoke(command);
+
+			assertThat(result).isTrue();
+		}
+
+		@Test
+		void shouldRevokeTrueWhenParentFailed() {
+			doReturn(true).when(service).isParentCommandFailed(any());
+
+			var result = service.shouldRevoke(CommandTestFactory.create());
+
+			assertThat(result).isTrue();
+		}
+	}
+
+	@Nested
+	class TestIsParentCommandFailed {
+
+		@Test
+		void shouldCallGetParentId() {
+			var command = CommandTestFactory.create();
+
+			service.isParentCommandFailed(command);
+
+			verify(service).getParentId(command);
+		}
+
+		@Test
+		void shouldReturnFalseWhenParentMissing() {
+			doReturn(Optional.empty()).when(service).getParentId(any());
+
+			var result = isParentCommandFailed();
+
+			assertThat(result).isFalse();
+		}
+
+		@Nested
+		class TestWithParent {
+
+			private static final String PARENT_ID = "parent-id";
+
+			@BeforeEach
+			void init() {
+				doReturn(Optional.of(PARENT_ID)).when(service).getParentId(any());
 			}
 
-			@DisplayName("should not call publishCommandExecutedEvent when no parent id")
 			@Test
-			void shouldNotCallPublishCommandExecutedEvent() {
-				doReturn(Optional.empty()).when(service).getCompletableParentId(any());
+			void shouldCallRepository() {
+				isParentCommandFailed();
 
-				service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
-
-				verify(service, never()).publishCommandExecutedEvent(anyString());
+				verify(repository).isCommandFailed(PARENT_ID);
 			}
 
-			@DisplayName("should not call publishCommandExecutedEvent when not all subcommands are finished")
 			@Test
-			void shouldNotCallPublishCommandExecutedEvent1() {
-				var parentId = "parent-id";
-				doReturn(Optional.of(parentId)).when(service).getCompletableParentId(any());
-				when(repository.existsNotFinishedSubCommands(any())).thenReturn(true);
+			void shouldReturnTrueWhenParentNotFailed() {
+				when(repository.isCommandFailed(any())).thenReturn(true);
 
-				service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+				var result = isParentCommandFailed();
 
-				verify(service, never()).publishCommandExecutedEvent(anyString());
+				assertThat(result).isTrue();
+			}
+
+			@Test
+			void shouldReturnFalseWhenParentFailed() {
+				var result = isParentCommandFailed();
+
+				assertThat(result).isFalse();
 			}
 		}
+
+		boolean isParentCommandFailed() {
+			return service.isParentCommandFailed(CommandTestFactory.create());
+		}
 	}
 
 	@Nested
 	class TestGetCompletableParentId {
 
+		private static final Command COMMAND = CommandTestFactory.create();
+
 		@Test
-		void shouldGetParentId() {
-			service.getCompletableParentId(CommandTestFactory.ID);
+		void shouldCallGetParentId() {
+			service.getCompletableParentId(COMMAND);
 
-			verify(repository).getParentId(CommandTestFactory.ID);
+			verify(service).getParentId(COMMAND);
 		}
 
 		@Test
-		void shouldFilterIfParentCompletableBySubCommands() {
-			var expectedParentId = "parent-id";
-			when(repository.getParentId(anyString())).thenReturn(Optional.of(expectedParentId));
+		void shouldReturnEmptyWhenNoParentId() {
+			doReturn(Optional.empty()).when(service).getParentId(any());
 
-			service.getCompletableParentId(CommandTestFactory.ID);
+			var result = service.getCompletableParentId(COMMAND);
 
-			verify(repository).isCompleteIfSubsCompleted(expectedParentId);
+			assertThat(result).isEmpty();
 		}
 
+		@Nested
+		class TestCompleteIfSubsCompleted {
+
+			private static final String PARENT_ID = "parent-id";
+
+			@BeforeEach
+			void init() {
+				doReturn(Optional.of(PARENT_ID)).when(service).getParentId(any());
+			}
+
+			@Test
+			void shouldCallIsCompleteIfSubsCompleted() {
+				service.getCompletableParentId(COMMAND);
+
+				verify(repository).isCompleteIfSubsCompleted(PARENT_ID);
+			}
+
+			@Test
+			void shouldCallExistsNotFinishedSubCommands() {
+				when(repository.isCompleteIfSubsCompleted(anyString())).thenReturn(true);
+
+				service.getCompletableParentId(COMMAND);
+
+				verify(repository).existsNotFinishedSubCommands(PARENT_ID);
+			}
+
+			@Test
+			void shouldReturnParentId() {
+				when(repository.isCompleteIfSubsCompleted(anyString())).thenReturn(true);
+
+				var result = service.getCompletableParentId(COMMAND);
+
+				assertThat(result).contains(PARENT_ID);
+			}
+
+			@Test
+			void shouldReturnEmptyWhenNotCompletableBySubCommands() {
+				var result = service.getCompletableParentId(COMMAND);
+
+				assertThat(result).isEmpty();
+			}
+		}
+
+	}
+
+	@Nested
+	class TestGetParentId {
+
 		@Test
-		void shouldReturnParentId() {
-			var expectedParentId = "parent-id";
-			doReturn(Optional.of(expectedParentId)).when(repository).getParentId(anyString());
-			when(repository.isCompleteIfSubsCompleted(anyString())).thenReturn(true);
+		void shouldReturnResult() {
+			var parentId = "parent-id";
+			var command = CommandTestFactory.createBuilder().bodyObject(Map.of(PersistedCommand.PROPERTY_PARENT_ID, parentId)).build();
 
-			var result = service.getCompletableParentId(CommandTestFactory.ID);
+			var result = service.getParentId(command);
 
-			assertThat(result).contains(expectedParentId);
+			assertThat(result).contains(parentId);
 		}
 
 		@Test
-		void shouldReturnEmptyWhenNoParentId() {
-			var result = service.getCompletableParentId(CommandTestFactory.ID);
+		void shouldReturnEmptyWhenNoBodyObject() {
+			var command = CommandTestFactory.createBuilder().bodyObject(null).build();
+
+			var result = service.getParentId(command);
 
 			assertThat(result).isEmpty();
 		}
 
 		@Test
-		void shouldReturnEmptyWhenNotCompletableBySubCommands() {
-			doReturn(Optional.of("parent-id")).when(repository).getParentId(anyString());
+		void shouldReturnEmptyWhenNoParentId() {
+			var command = CommandTestFactory.createBuilder().bodyObject(Map.of()).build();
 
-			var result = service.getCompletableParentId(CommandTestFactory.ID);
+			var result = service.getParentId(command);
 
 			assertThat(result).isEmpty();
 		}
@@ -402,111 +538,171 @@ class CommandServiceTest {
 	class TestSetCommandError {
 
 		private static final String ERROR_MESSAGE = "error message";
-
-		@Captor
-		private ArgumentCaptor<CommandFailedEvent> eventCaptor;
+		private static final String PARENT_ID = "parent-id";
 
 		@Test
-		void shouldCallRepository() {
+		void shouldCallRepositorySetErrorMessage() {
 			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
 
 			verify(repository).setErrorMessage(CommandTestFactory.ID, ERROR_MESSAGE);
 		}
 
 		@Test
-		void shouldCallFindNotFailedSubCommandIds() {
+		void shouldCallRepositoryGetParentId() {
 			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
 
-			verify(repository).findNotFailedSubCommandIds(CommandTestFactory.ID);
+			verify(repository).getParentId(CommandTestFactory.ID);
 		}
 
-		@Test
-		void shouldPublishCommandFailedEvent() {
-			var notFailedCommandId = "not-failed-command-id";
-			when(repository.findNotFailedSubCommandIds(anyString())).thenReturn(Stream.of(notFailedCommandId));
+		@Nested
+		class TestFailParentAndRevokeSubCommands {
 
-			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+			private static final Command COMMAND_BEFORE_SET_ERROR_STATUS = CommandTestFactory.createBuilder().id(PARENT_ID).build();
 
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue().getSource()).isEqualTo(notFailedCommandId);
+			@BeforeEach
+			void init() {
+				when(repository.getParentId(anyString())).thenReturn(Optional.of(PARENT_ID));
+				doReturn(COMMAND_BEFORE_SET_ERROR_STATUS).when(service).setErrorStatus(anyString());
+			}
+
+			@Test
+			void shouldCallSetErrorStatus() {
+				service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+
+				verify(service).setErrorStatus(PARENT_ID);
+			}
+
+			@Test
+			void shouldCallNotErrorStatus() {
+				service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+
+				verify(service).notErrorStatus(COMMAND_BEFORE_SET_ERROR_STATUS);
+			}
+
+			@Test
+			void shouldCallHandleCommandError() {
+				service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+
+				verify(service).handleCommandError(CommandTestFactory.ID, PARENT_ID);
+			}
 		}
 
-		@Test
-		void shouldFilterOwnId() {
-			when(repository.findNotFailedSubCommandIds(anyString())).thenReturn(Stream.of(CommandTestFactory.ID));
+		@Nested
+		class TestParentIdMissing {
 
-			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+			@BeforeEach
+			void init() {
+				doReturn(Optional.empty()).when(repository).getParentId(anyString());
+			}
 
-			verify(publisher, never()).publishEvent(any());
+			@Test
+			void shouldNotCallHandleCommandError() {
+				service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+
+				verify(service, never()).handleCommandError(anyString(), anyString());
+			}
 		}
 
-		@Test
-		void shouldNotCallPublishCommandFailedEventIfNoNotFailedSubCommands() {
-			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+		@Nested
+		class TestParentAlreadyFailed {
+
+			@Mock
+			private Command failedParentCommand;
+
+			@BeforeEach
+			void init() {
+				when(repository.getParentId(anyString())).thenReturn(Optional.of(PARENT_ID));
+				doReturn(failedParentCommand).when(service).setErrorStatus(anyString());
+				doReturn(false).when(service).notErrorStatus(any());
+			}
 
-			verify(publisher, never()).publishEvent(any());
+			@Test
+			void shouldNotCallHandleCommandError() {
+				service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+
+				verify(service, never()).handleCommandError(anyString(), anyString());
+			}
 		}
 
+	}
+
+	@Nested
+	class TestSetErrorStatus {
+
 		@Test
-		void shouldCallGetNotFailedParentId() {
-			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+		void shouldCallRepositoryUpdateStatus() {
+			when(repository.updateCommandStatusAndReturnPrevious(anyString(), any())).thenReturn(CommandTestFactory.create());
+
+			service.setErrorStatus(CommandTestFactory.ID);
 
-			verify(repository).getNotFailedParentId(CommandTestFactory.ID);
+			verify(repository).updateCommandStatusAndReturnPrevious(CommandTestFactory.ID, CommandStatus.ERROR);
 		}
 
 		@Test
-		void shouldCallPublishCommandFailedEventForParent() {
-			var parentId = "parent-id";
-			when(repository.getNotFailedParentId(anyString())).thenReturn(Optional.of(parentId));
+		void shouldReturnCommand() {
+			var command = CommandTestFactory.create();
+			when(repository.updateCommandStatusAndReturnPrevious(anyString(), any())).thenReturn(command);
 
-			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+			var result = service.setErrorStatus(CommandTestFactory.ID);
 
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue().getSource()).isEqualTo(parentId);
+			assertThat(result).isSameAs(command);
 		}
 
 		@Test
-		void shouldNotCallPublishCommandFailedEventForParentIfNoParent() {
-			service.setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
-
-			verify(publisher, never()).publishEvent(any());
+		void shouldThrowExceptionIfNotFound() {
+			assertThrows(NotFoundException.class, () -> service.setErrorStatus(CommandTestFactory.ID));
 		}
 	}
 
 	@Nested
-	class TestCreateCommandFailedEventPublisher {
+	class TestNotErrorStatus {
 
-		private static final String EXPECTED_ERROR_MESSAGE = "error message";
+		@DisplayName("should return true when")
+		@ParameterizedTest(name = "command status is {0}")
+		@EnumSource(value = CommandStatus.class, names = { "ERROR" }, mode = EnumSource.Mode.EXCLUDE)
+		void shouldReturnTrue(CommandStatus status) {
+			var command = CommandTestFactory.createBuilder().status(status).build();
 
-		@Captor
-		private ArgumentCaptor<CommandFailedEvent> eventCaptor;
+			var result = service.notErrorStatus(command);
+
+			assertThat(result).isTrue();
+		}
 
 		@Test
-		void shouldPublishCommandFailedEvent() {
-			publishCommandFailedEvent();
+		void shouldReturnFalse() {
+			var command = CommandTestFactory.createBuilder().status(CommandStatus.ERROR).build();
 
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue()).isInstanceOf(CommandFailedEvent.class);
+			var result = service.notErrorStatus(command);
+
+			assertThat(result).isFalse();
 		}
+	}
+
+	@Nested
+	class TestHandleCommandError {
+
+		private static final String PARENT_ID = "parent-id";
+
+		@Captor
+		private ArgumentCaptor<String> errorMessageCaptor;
 
 		@Test
-		void shouldSetCommandIdInFailedEvent() {
-			publishCommandFailedEvent();
+		void shouldCallPublishCommandFailedEvent() {
+			handleCommandError();
 
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue().getErrorMessage()).isEqualTo(EXPECTED_ERROR_MESSAGE);
+			verify(service).publishCommandFailedEvent(eq(PARENT_ID), errorMessageCaptor.capture());
+			assertThat(errorMessageCaptor.getValue()).contains(PARENT_ID, CommandTestFactory.ID);
 		}
 
 		@Test
-		void shouldSetErrorMessageInFailedEvent() {
-			publishCommandFailedEvent();
+		void shouldCallRevokeSubCommands() {
+			handleCommandError();
 
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue().getErrorMessage()).isEqualTo(EXPECTED_ERROR_MESSAGE);
+			verify(service).revokeSubCommands(PARENT_ID);
 		}
 
-		private void publishCommandFailedEvent() {
-			service.createCommandFailedEventPublisher(EXPECTED_ERROR_MESSAGE).accept(CommandTestFactory.ID);
+		private void handleCommandError() {
+			service.handleCommandError(CommandTestFactory.ID, PARENT_ID);
 		}
 	}
 
@@ -524,40 +720,106 @@ class CommandServiceTest {
 	@Nested
 	class TestRevokeCommand {
 
-		final String commandId = CommandTestFactory.ID;
+		private static final Command REVOKE_PENDING_COMMAND = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build();
 
 		@Test
-		void shouldThrowException() {
-			assertThatExceptionOfType(NotFoundException.class).isThrownBy(() -> service.revokeCommand(commandId));
+		void shouldCallRevokeCommandSilent() {
+			doReturn(Optional.of(REVOKE_PENDING_COMMAND)).when(service).revokeCommandSilent(anyString());
+
+			service.revokeCommand(CommandTestFactory.ID);
+
+			verify(service).revokeCommandSilent(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallIsRevokePending() {
+			doReturn(Optional.of(REVOKE_PENDING_COMMAND)).when(service).revokeCommandSilent(anyString());
+
+			service.revokeCommand(CommandTestFactory.ID);
+
+			verify(service).isRevokePending(REVOKE_PENDING_COMMAND);
+		}
+
+		@Test
+		void shouldReturnCommand() {
+			doReturn(Optional.of(REVOKE_PENDING_COMMAND)).when(service).revokeCommandSilent(anyString());
+
+			var result = service.revokeCommand(CommandTestFactory.ID);
+
+			assertThat(result).isSameAs(REVOKE_PENDING_COMMAND);
+		}
+
+		@Test
+		void shouldThrowNotFoundException() {
+			doReturn(Optional.empty()).when(service).revokeCommandSilent(anyString());
+
+			assertThrows(NotFoundException.class, () -> service.revokeCommand(CommandTestFactory.ID));
 		}
 
 		@Test
-		void shouldCallSetRevokeStatus() {
-			doReturn(CommandTestFactory.create()).when(repository).setRevokeStatus(anyString());
+		void shouldThrowRevokeFailedException() {
+			doReturn(Optional.of(CommandTestFactory.create())).when(service).revokeCommandSilent(anyString());
+			doReturn(false).when(service).isRevokePending(any());
 
-			service.revokeCommand(commandId);
+			assertThrows(RevokeFailedException.class, () -> service.revokeCommand(CommandTestFactory.ID));
+		}
+	}
+
+	@Nested
+	class TestRevokeCommandSilent {
+
+		private static final Command COMMAND = CommandTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(repository.setRevokeStatusIfNotPending(anyString())).thenReturn(Optional.of(COMMAND));
+		}
+
+		@Test
+		void shouldCallRepository() {
+			service.revokeCommandSilent(CommandTestFactory.ID);
+
+			verify(repository).setRevokeStatusIfNotPending(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallIsRevokePending() {
+			service.revokeCommandSilent(CommandTestFactory.ID);
 
-			verify(service).setRevokeStatus(CommandTestFactory.ID);
+			verify(service).isRevokePending(COMMAND);
 		}
 
 		@Test
 		void shouldCallPublishRevokeCommandEvent() {
-			var command = CommandTestFactory.create();
-			doReturn(command).when(repository).setRevokeStatus(anyString());
+			doReturn(true).when(service).isRevokePending(any());
 
-			service.revokeCommand(commandId);
+			service.revokeCommandSilent(CommandTestFactory.ID);
 
-			verify(service).publishRevokeCommandEvent(command);
+			verify(service).publishRevokeCommandEvent(COMMAND);
 		}
+	}
+
+	@Nested
+	class TestIsRevokePending {
 
 		@Test
-		void shouldReturnCommand() {
-			var command = CommandTestFactory.create();
-			doReturn(command).when(repository).setRevokeStatus(anyString());
+		void shouldReturnTrue() {
+			var command = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build();
 
-			var result = service.revokeCommand(commandId);
+			var result = service.isRevokePending(command);
 
-			assertThat(result).isSameAs(command);
+			assertThat(result).isTrue();
+		}
+
+		@DisplayName("should return false when")
+		@ParameterizedTest(name = "command status is {0}")
+		@EnumSource(value = CommandStatus.class, names = { "REVOKE_PENDING" }, mode = EnumSource.Mode.EXCLUDE)
+		void shouldReturnFalse(CommandStatus status) {
+			var command = CommandTestFactory.createBuilder().status(status).build();
+
+			var result = service.isRevokePending(command);
+
+			assertThat(result).isFalse();
 		}
 	}
 
@@ -664,14 +926,14 @@ class CommandServiceTest {
 		@BeforeEach
 		void init() {
 			doReturn(SUB_COMMAND_VALUES).when(service).buildSubCommandValues(any());
-			doReturn(PARENT_COMMAND).when(service).getNotFailedCommand(any());
+			doReturn(PARENT_COMMAND).when(service).getPendingCommand(any());
 		}
 
 		@Test
 		void shouldCallGetNotFailedCommand() {
 			service.createSubCommands(CreateSubCommandsRequestTestFactory.create());
 
-			verify(service).getNotFailedCommand(CreateSubCommandsRequestTestFactory.PARENT_ID);
+			verify(service).getPendingCommand(CreateSubCommandsRequestTestFactory.PARENT_ID);
 		}
 
 		@Test
@@ -722,30 +984,25 @@ class CommandServiceTest {
 	}
 
 	@Nested
-	class TestGetNotFailedCommand {
+	class TestGetPendingCommand {
 
 		@Test
 		void shouldCallFindCommand() {
 			doReturn(Optional.of(CommandTestFactory.create())).when(service).findById(anyString());
 
-			service.getNotFailedCommand(CommandTestFactory.ID);
+			service.getPendingCommand(CommandTestFactory.ID);
 
 			verify(service).findById(CommandTestFactory.ID);
 		}
 
-		@Test
-		void shouldThrowExceptionIfCommandNotFound() {
-			doReturn(Optional.empty()).when(service).findById(anyString());
-
-			assertThrows(NotFoundException.class, () -> service.getNotFailedCommand(CommandTestFactory.ID));
-		}
-
-		@Test
-		void shouldThrowExceptionIfCommandFailed() {
-			var command = CommandTestFactory.createBuilder().status(CommandStatus.ERROR).build();
-			doReturn(Optional.of(command)).when(service).findById(anyString());
+		@DisplayName("should throw exception when")
+		@ParameterizedTest(name = "command status is {0}")
+		@EnumSource(value = CommandStatus.class, names = { "PENDING" }, mode = EnumSource.Mode.EXCLUDE)
+		void shouldThrowExceptionIfCommandFailed(CommandStatus status) {
+			var command = CommandTestFactory.createBuilder().status(status).build();
+			doReturn(command).when(service).getById(anyString());
 
-			assertThrows(TechnicalException.class, () -> service.getNotFailedCommand(CommandTestFactory.ID));
+			assertThrows(TechnicalException.class, () -> service.getPendingCommand(CommandTestFactory.ID));
 		}
 
 		@Test
@@ -753,7 +1010,7 @@ class CommandServiceTest {
 			var command = CommandTestFactory.create();
 			doReturn(Optional.of(command)).when(service).findById(anyString());
 
-			var result = service.getNotFailedCommand(CommandTestFactory.ID);
+			var result = service.getPendingCommand(CommandTestFactory.ID);
 
 			assertThat(result).isSameAs(command);
 		}
@@ -857,24 +1114,4 @@ class CommandServiceTest {
 		}
 	}
 
-	@Nested
-	class TestSetStatusRevokePending {
-
-		@Test
-		void shouldCallRepository() {
-			service.setRevokeStatus(CommandTestFactory.ID);
-
-			verify(repository).setRevokeStatus(CommandTestFactory.ID);
-		}
-
-		@Test
-		void shouldReturnUpdatedCommand() {
-			var expectedCommand = CommandTestFactory.create();
-			when(repository.setRevokeStatus(anyString())).thenReturn(expectedCommand);
-
-			var result = service.setRevokeStatus(CommandTestFactory.ID);
-
-			assertThat(result).isSameAs(expectedCommand);
-		}
-	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
index 3053fad919a61cbdc56dfc0a5e0a46fd92a193e8..7df40567d8e858171053fe352454a7e67decde01 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
@@ -21,7 +21,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.data.mongodb.core.MongoOperations;
-import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.annotation.DirtiesContext;
 
 import de.ozgcloud.command.Command;
@@ -29,20 +28,20 @@ import de.ozgcloud.command.CommandStatus;
 import de.ozgcloud.common.test.DataITCase;
 import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
 import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.callcontext.WithMockCustomUser;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
 import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
 import de.ozgcloud.vorgang.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
 import de.ozgcloud.vorgang.grpc.command.GrpcAddSubCommandsRequest;
 import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
-import de.ozgcloud.vorgang.grpc.command.GrpcCommandsResponse;
 import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommand;
 import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
 import de.ozgcloud.vorgang.grpc.command.GrpcFindCommandsRequest;
-import de.ozgcloud.vorgang.grpc.command.GrpcGetCommandRequest;
 import de.ozgcloud.vorgang.grpc.command.GrpcRevokeCommandRequest;
 import de.ozgcloud.vorgang.vorgang.Vorgang;
 import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.StatusRuntimeException;
+import lombok.extern.log4j.Log4j2;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @SpringBootTest(properties = {
@@ -51,7 +50,8 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
 })
 @DirtiesContext
 @DataITCase
-@WithMockUser
+@WithMockCustomUser
+@Log4j2
 class GrpcCommandServiceITCase {
 
 	@GrpcClient("inProcess")
@@ -155,7 +155,6 @@ class GrpcCommandServiceITCase {
 	}
 
 	@Nested
-			// TODO Tests überarbeiten: asserts in Test-Methoden verschieben
 	class TestAddSubCommands {
 
 		private static final String PARENT_TEST_ORDER = "PARENT_TEST_ORDER";
@@ -181,51 +180,39 @@ class GrpcCommandServiceITCase {
 
 			var grpcCommandsResponse = serviceBlockingStub.addSubCommands(request);
 
-			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> assertCommandIsFinished(parentCommand));
-			grpcCommandsResponse.getCommandList().forEach(this::assertCommandIsFinished);
+			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> {
+				var command = loadCommand(parentCommand);
+				assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
+			});
+			grpcCommandsResponse.getCommandList().stream().map(this::loadCommand).forEach(command ->
+					assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED)
+			);
 		}
 
 		@Test
-		void shouldSetErrorWhenOneOfParallelsFails() {
+		void shouldSetErrorStatusForParentCommand() {
 			var request = buildAddSubCommandsRequest(parentCommand.getId(), buildCreateCommand(), buildFailedCreateCommand(), buildCreateCommand());
 
-			var grpcCommandsResponse = serviceBlockingStub.addSubCommands(request);
+			serviceBlockingStub.addSubCommands(request);
 
-			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> assertCommandIsFailed(parentCommand));
-			grpcCommandsResponse.getCommandList().forEach(this::assertCommandIsFailed);
-		}
-
-		@Test
-		void shouldSetErrorWhenOneSequentialFails() {
-			var executedCommands = addSuccessfullySubCommands();
-
-			var failedCommand = addFailedSubCommands();
-
-			failedCommand.getCommandList().forEach(this::assertCommandIsFailed);
-			executedCommands.getCommandList().forEach(this::assertCommandIsFailed);
+			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> {
+				var command = loadCommand(parentCommand);
+				assertThat(command.getStatus()).isEqualTo(CommandStatus.ERROR);
+				assertThat(command.getErrorMessage()).isNotBlank();
+			});
 		}
 
 		@Test
-		void shouldThrowErrorWhenParentFailedAlready() {
-			addFailedSubCommands();
-
-			assertThrows(StatusRuntimeException.class, this::addSuccessfullySubCommands);
-		}
-
-		private GrpcCommandsResponse addSuccessfullySubCommands() {
-			var successfullyRequest = buildAddSubCommandsRequest(parentCommand.getId(), buildCreateCommand());
-			var executedCommands = serviceBlockingStub.addSubCommands(successfullyRequest);
-			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> assertCommandIsFinished(parentCommand));
-			return executedCommands;
-		}
-
-		private GrpcCommandsResponse addFailedSubCommands() {
-			var failedRequest = buildAddSubCommandsRequest(parentCommand.getId(), buildFailedCreateCommand());
+		void shouldRevokeSubCommands() {
+			var request = buildAddSubCommandsRequest(parentCommand.getId(), buildCreateCommand(), buildFailedCreateCommand(), buildCreateCommand());
 
-			var executedCommands = serviceBlockingStub.addSubCommands(failedRequest);
+			var grpcCommandsResponse = serviceBlockingStub.addSubCommands(request);
 
-			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> assertCommandIsFailed(parentCommand));
-			return executedCommands;
+			await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> {
+				var revokedCommand = grpcCommandsResponse.getCommandList().stream().map(this::loadCommand)
+						.filter(command -> command.getStatus() != CommandStatus.ERROR).toList();
+				assertThat(revokedCommand).hasSize(2);
+			});
 		}
 
 		private GrpcCommand createParentCommand() {
@@ -268,15 +255,13 @@ class GrpcCommandServiceITCase {
 					.build();
 		}
 
-		private void assertCommandIsFinished(GrpcCommand command) {
-			var commandResponse = serviceBlockingStub.getCommand(GrpcGetCommandRequest.newBuilder().setId(command.getId()).build());
-			assertThat(commandResponse.getStatus()).isEqualTo(CommandStatus.FINISHED.name());
+		private Command loadCommand(GrpcCommand grpcCommand) {
+			return mongoOperations.findById(grpcCommand.getId(), Command.class);
 		}
 
-		private void assertCommandIsFailed(GrpcCommand command) {
-			var commandResponse = serviceBlockingStub.getCommand(GrpcGetCommandRequest.newBuilder().setId(command.getId()).build());
-			assertThat(commandResponse.getStatus()).isEqualTo(CommandStatus.ERROR.name());
+		private void assertCommandIsFinished(GrpcCommand grpcCommand) {
+			var command = mongoOperations.findById(grpcCommand.getId(), Command.class);
+			assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
 		}
-
 	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java
index 149bd64d92c2013acd67bd8502b7dd195b662347..6807b332b138383be4bff92001a809aba224d3ac 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java
@@ -199,16 +199,29 @@ class GrpcCommandServiceTest {
 	@Nested
 	class TestRevokeCommand {
 
+		private static final GrpcRevokeCommandRequest REVOKE_COMMAND_REQUEST = GrpcRevokeCommandRequest.newBuilder().setId(CommandTestFactory.ID)
+				.build();
+
 		@Mock
 		private StreamObserver<GrpcCommandResponse> responseObserver;
-		private final Command updatedCommand = CommandTestFactory.createBuilder().id(CommandTestFactory.ID).build();
+
 		@Mock
 		private GrpcCommandResponse commandsResponse;
 
-		private final GrpcRevokeCommandRequest request = GrpcRevokeCommandRequest.newBuilder().setId(CommandTestFactory.ID).build();
 		@Captor
 		private ArgumentCaptor<CommandResponse> responseCaptor;
 
+		private Command updatedCommand;
+
+		private void callRevokeCommand() {
+			service.revokeCommand(REVOKE_COMMAND_REQUEST, responseObserver);
+		}
+
+		@BeforeEach
+		void init() {
+			updatedCommand = CommandTestFactory.createBuilder().id(CommandTestFactory.ID).build();
+		}
+
 		@Test
 		void shouldCallPolicyService() {
 			callRevokeCommand();
@@ -248,10 +261,6 @@ class GrpcCommandServiceTest {
 
 			verify(responseObserver).onCompleted();
 		}
-
-		private void callRevokeCommand() {
-			service.revokeCommand(request, responseObserver);
-		}
 	}
 
 	@Nested