diff --git a/joern-cli/frontends/rubysrc2cpg/src/main/resources/log4j2.xml b/joern-cli/frontends/rubysrc2cpg/src/main/resources/log4j2.xml
new file mode 100644
index 000000000000..ab3b2d88c5e4
--- /dev/null
+++ b/joern-cli/frontends/rubysrc2cpg/src/main/resources/log4j2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+    <Appenders>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout pattern="[%-5p] %m%n" />
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="${env:SL_LOGGING_LEVEL:-info}">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/parser/AntlrParser.scala b/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/parser/AntlrParser.scala
index 498f1c4b0328..5e279c667cfb 100644
--- a/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/parser/AntlrParser.scala
+++ b/joern-cli/frontends/rubysrc2cpg/src/main/scala/io/joern/rubysrc2cpg/parser/AntlrParser.scala
@@ -1,10 +1,12 @@
 package io.joern.rubysrc2cpg.parser
 
 import org.antlr.v4.runtime.*
-import org.antlr.v4.runtime.atn.ATN
+import org.antlr.v4.runtime.atn.{ATN, ATNConfigSet}
 import org.antlr.v4.runtime.dfa.DFA
 import org.slf4j.LoggerFactory
 
+import java.util
+import scala.collection.mutable.ListBuffer
 import scala.util.Try
 
 /** A consumable wrapper for the RubyParser class used to parse the given file and be disposed thereafter.
@@ -18,7 +20,52 @@ class AntlrParser(filename: String) {
   private val tokenStream = new CommonTokenStream(RubyLexerPostProcessor(lexer))
   val parser: RubyParser  = new RubyParser(tokenStream)
 
-  def parse(): Try[RubyParser.ProgramContext] = Try(parser.program())
+  def parse(): (Try[RubyParser.ProgramContext], List[String]) = {
+    val errors = ListBuffer[String]()
+    parser.removeErrorListeners()
+    parser.addErrorListener(new ANTLRErrorListener {
+      override def syntaxError(
+        recognizer: Recognizer[_, _],
+        offendingSymbol: Any,
+        line: Int,
+        charPositionInLine: Int,
+        msg: String,
+        e: RecognitionException
+      ): Unit = {
+        val errorMessage = s"Syntax error on $filename:$line:$charPositionInLine"
+        errors.append(errorMessage)
+      }
+
+      override def reportAmbiguity(
+        recognizer: Parser,
+        dfa: DFA,
+        startIndex: Int,
+        stopIndex: Int,
+        exact: Boolean,
+        ambigAlts: util.BitSet,
+        configs: ATNConfigSet
+      ): Unit = {}
+
+      override def reportAttemptingFullContext(
+        recognizer: Parser,
+        dfa: DFA,
+        startIndex: Int,
+        stopIndex: Int,
+        conflictingAlts: util.BitSet,
+        configs: ATNConfigSet
+      ): Unit = {}
+
+      override def reportContextSensitivity(
+        recognizer: Parser,
+        dfa: DFA,
+        startIndex: Int,
+        stopIndex: Int,
+        prediction: Int,
+        configs: ATNConfigSet
+      ): Unit = {}
+    })
+    (Try(parser.program()), errors.toList)
+  }
 }
 
 /** A re-usable parser object that clears the ANTLR DFA-cache if it determines that the memory usage is becoming large.
@@ -49,7 +96,9 @@ class ResourceManagedParser(clearLimit: Double) extends AutoCloseable {
       logger.info(s"Runtime memory consumption at $usedMemory, clearing ANTLR DFA cache")
       clearDFA()
     }
-    antlrParser.parse()
+    val (programCtx, errors) = antlrParser.parse()
+    errors.foreach(logger.warn)
+    programCtx
   }
 
   /** Clears the shared DFA cache.