diff --git a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala
index 17631709f12db8a3e3b25253afc49fadd3820e32..abeb787a5e15d4b0ad6baf3eb8f7a7c1708232ec 100644
--- a/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala
+++ b/public/biopet-core/src/main/scala/nl/lumc/sasc/biopet/core/MultiSampleQScript.scala
@@ -18,7 +18,7 @@ package nl.lumc.sasc.biopet.core
 import java.io.File
 
 import nl.lumc.sasc.biopet.core.summary.{ Summarizable, SummaryQScript }
-import nl.lumc.sasc.biopet.utils.ConfigUtils
+import nl.lumc.sasc.biopet.utils.{ Logging, ConfigUtils }
 import org.broadinstitute.gatk.utils.commandline.Argument
 
 /** This trait creates a structured way of use multisample pipelines */
@@ -90,6 +90,8 @@ trait MultiSampleQScript extends SummaryQScript {
 
     /** Adds sample jobs */
     final def addAndTrackJobs(): Unit = {
+      if (sampleRegex.findFirstIn(sampleId) == None)
+        Logging.addError(s"Sample '$sampleId' contains illegal chars")
       currentSample = Some(sampleId)
       addJobs()
       qscript.addSummarizable(this, "pipeline", Some(sampleId))
@@ -129,6 +131,8 @@ trait MultiSampleQScript extends SummaryQScript {
   /** Returns a list of all sampleIDs */
   protected def sampleIds: Set[String] = ConfigUtils.any2map(globalConfig.map("samples")).keySet
 
+  protected lazy val sampleRegex = """^[a-zA-Z0-9-_]+$""".r
+
   /** Runs addAndTrackJobs method for each sample */
   final def addSamplesJobs() {
     if (onlySamples.isEmpty || samples.forall(x => onlySamples.contains(x._1))) {