diff --git a/src/main/jastadd/Coordinator.jrag b/src/main/jastadd/Coordinator.jrag
index 1f9a8a201da38baff7948e4bb9466e3f9669f02a..c7bd041e509f7c978000959462da2dd67f9251c4 100644
--- a/src/main/jastadd/Coordinator.jrag
+++ b/src/main/jastadd/Coordinator.jrag
@@ -49,10 +49,10 @@ aspect Manipulation {
       return Collections.emptySet();
     }
     for (String service : services) {
-      resolveComponentByDockerComposeName(service).ifPresentOrElse(
-        comp -> result.add(comp),
-        () -> System.err.println("Could not resolve docker component for '" + service + "'!")
-      );
+      Component resolvedComponent = resolveComponentByDockerComposeName(service);
+      if (!resolvedComponent.handleFailedComponentResolving("Service", () -> "resolving docker compose")) {
+        result.add(resolvedComponent);
+      }
     }
     return result;
   }
@@ -137,6 +137,9 @@ aspect Navigation {
 
   syn MqttReportStrategy ReportStrategy.asMqttReportStrategy() = null;
   eq MqttReportStrategy.asMqttReportStrategy() = this;
+
+  syn boolean Component.isUnknownComponent() = false;
+  eq UnknownComponent.isUnknownComponent() = true;
 }
 
 aspect Printing {
@@ -222,31 +225,65 @@ aspect Printing {
 }
 
 aspect Resolving {
-  syn Optional<Component> Coordinator.resolveComponent(String name) {
+  public enum ResolvingFailedStrategy {
+    IGNORE,
+    WARNING,
+    EXIT
+  }
+
+  public static ResolvingFailedStrategy Coordinator.RESOLVING_FAILED_STRATEGY = ResolvingFailedStrategy.EXIT;
+
+  syn nta Component Coordinator.unknownComponent(String id) = new UnknownComponent().setName(id);
+
+  syn Component Coordinator.resolveComponent(String name) {
     for (Component comp : getComponentList()) {
       if (comp.getName().equals(name)) {
-        return Optional.of(comp);
+        return comp;
       }
     }
-    return Optional.empty();
+    return unknownComponent(name);
   }
 
-  syn Optional<Component> Coordinator.resolveComponentByDockerComposeName(String dockerComposeName) {
+  syn Component Coordinator.resolveComponentByDockerComposeName(String dockerComposeName) {
     for (Component comp : getComponentList()) {
       if (comp.getStartStrategy().isDockerComposeStartStrategy() &&
           comp.getStartStrategy().asDockerComposeStartStrategy().getName().equals(dockerComposeName)) {
-        return Optional.of(comp);
+        return comp;
       }
     }
-    return Optional.empty();
+    return unknownComponent(dockerComposeName);
   }
 
   refine RefResolverStubs eq ParsedPrecedenceRelation.resolvePredecessorByToken(String id, int position) {
-    return coordinator().resolveComponent(id).orElseThrow(() -> new RuntimeException("Predecessor '" + id + "' not found in " + this.prettyPrint() + "!"));
+    return coordinator().resolveComponent(id);
   }
 
   refine RefResolverStubs eq ParsedPrecedenceRelation.resolveSuccessorByToken(String id, int position) {
-    return coordinator().resolveComponent(id).orElseThrow(() -> new RuntimeException("Successor '" + id + "' not found in " + this.prettyPrint() + "!"));
+    return coordinator().resolveComponent(id);
+  }
+
+  /**
+   * Handles component resolving based on the current strategy.
+   * If the component is an unknownComponent, decide based on RESOLVING_FAILED_STRATEGY what to do.
+   * Either do nothing (IGNORE), print a message (WARNING), or throw a RuntimeException (EXIT).
+   * @return false if a real component was resolved, true if this is an unknown component
+   */
+  public boolean Component.handleFailedComponentResolving(String kind, java.util.function.Supplier<String> context) {
+    return false;
+  }
+  @Override
+  public boolean UnknownComponent.handleFailedComponentResolving(String kind, java.util.function.Supplier<String> context) {
+    String message = kind + " '" + getName() + "' not found in " + context.get() + "!";
+    switch (Coordinator.RESOLVING_FAILED_STRATEGY) {
+      case IGNORE:
+        break;
+      case WARNING:
+        System.err.println(message);
+        break;
+      case EXIT:
+        throw new RuntimeException(message);
+    }
+    return true;
   }
 }
 
diff --git a/src/main/jastadd/Coordinator.parser b/src/main/jastadd/Coordinator.parser
index a1bb3f64f4db8a49c5d95284effd3b03c609a72f..1b5e9d8f5dd5fe9e489d4e9882e29c46aad4be7f 100644
--- a/src/main/jastadd/Coordinator.parser
+++ b/src/main/jastadd/Coordinator.parser
@@ -13,7 +13,9 @@ import java.util.HashMap;
   private void replaceRelations(Coordinator o) {
     for (ParsedPrecedenceRelation rel : o.getParsedPrecedenceRelationList()) {
       for (Component pred : rel.getPredecessorList()) {
+        if (pred.handleFailedComponentResolving("Predecessor", () -> rel.prettyPrint())) { continue; }
         for (Component succ : rel.getSuccessorList()) {
+          if (succ.handleFailedComponentResolving("Successor", () -> rel.prettyPrint())) { continue; }
           pred.addSuccessor(succ);
         }
       }
diff --git a/src/main/jastadd/Coordinator.relast b/src/main/jastadd/Coordinator.relast
index 11abd3738d7b0b8732d2ea632edee9308925a0fa..3eb491c327cfa7f3268e7a88d33a4326724126fb 100644
--- a/src/main/jastadd/Coordinator.relast
+++ b/src/main/jastadd/Coordinator.relast
@@ -15,3 +15,6 @@ AutoSetStatus ::= <Status:String> <DelayInSeconds:int> ;
 ParsedPrecedenceRelation ;
 rel ParsedPrecedenceRelation.Predecessor* -> Component ;
 rel ParsedPrecedenceRelation.Successor* -> Component ;
+
+// Parser-only
+UnknownComponent : Component ;
diff --git a/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java b/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java
index 7ccd1f6085742164b91ab4a3fcfeb345c3a70650..c3923ebf881340bd90371fdb948bb76045e677a5 100644
--- a/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java
+++ b/src/main/java/de/tudresden/inf/st/coordinator/MainCoordinator.java
@@ -1,10 +1,7 @@
 package de.tudresden.inf.st.coordinator;
 
 import beaver.Parser;
-import de.tudresden.inf.st.coordinator.ast.Component;
-import de.tudresden.inf.st.coordinator.ast.Coordinator;
-import de.tudresden.inf.st.coordinator.ast.MqttHandler;
-import de.tudresden.inf.st.coordinator.ast.MqttReportStrategy;
+import de.tudresden.inf.st.coordinator.ast.*;
 import de.tudresden.inf.st.coordinator.parser.CoordinatorParser;
 import de.tudresden.inf.st.coordinator.scanner.CoordinatorScanner;
 import picocli.CommandLine;
@@ -45,17 +42,23 @@ public class MainCoordinator implements Callable<Integer> {
   @Option(names = { "--mqtt-host"}, description = "MQTT host to control this coordinator")
   String mqttHost = "localhost";
 
+  @Option(names = { "-r", "--resolvingFailedStrategy"}, description = "Action if resolving of component fails, do nothing (IGNORE), print a message (WARNING), or throw a RuntimeException (EXIT)")
+  ResolvingFailedStrategy resolvingFailedStrategy = ResolvingFailedStrategy.EXIT;
+
   @Parameters(description = "Coordinator config file to use")
   File configFile;
 
   public static void main(String[] args) {
-    int exitCode = new CommandLine(new MainCoordinator()).execute(args);
+    int exitCode = new CommandLine(new MainCoordinator())
+        .setCaseInsensitiveEnumValuesAllowed(true)
+        .execute(args);
     System.exit(exitCode);
   }
 
   @Override
   public Integer call() throws Exception {
     Coordinator.DRY_RUN = dryRun;
+    Coordinator.RESOLVING_FAILED_STRATEGY = resolvingFailedStrategy;
     parsedBuild();
     return start();
   }