diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95dec064..1098b23d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
+### Added
+- Add `stackTrace` prop to `Exception` message ([#182](https://github.com/cucumber/messages/pull/182))
 
 ## [23.0.0] - 2023-11-01
 ### Added
diff --git a/cpp/include/cucumber/messages/exception.hpp b/cpp/include/cucumber/messages/exception.hpp
index c231ca4e..be55c71e 100644
--- a/cpp/include/cucumber/messages/exception.hpp
+++ b/cpp/include/cucumber/messages/exception.hpp
@@ -22,6 +22,7 @@ struct exception
 {
     std::string type;
     std::optional<std::string> message;
+    std::optional<std::string> stack_trace;
 
     std::string to_string() const;
 
diff --git a/cpp/src/lib/cucumber-messages/cucumber/messages/exception.cpp b/cpp/src/lib/cucumber-messages/cucumber/messages/exception.cpp
index c7a6a29c..e6ea57a7 100644
--- a/cpp/src/lib/cucumber-messages/cucumber/messages/exception.cpp
+++ b/cpp/src/lib/cucumber-messages/cucumber/messages/exception.cpp
@@ -12,6 +12,7 @@ exception::to_string() const
 
     cucumber::messages::to_string(oss, "type=", type);
     cucumber::messages::to_string(oss, ", message=", message);
+    cucumber::messages::to_string(oss, ", stack_trace=", stack_trace);
 
     return oss.str();
 }
@@ -21,6 +22,7 @@ exception::to_json(json& j) const
 {
     cucumber::messages::to_json(j, camelize("type"), type);
     cucumber::messages::to_json(j, camelize("message"), message);
+    cucumber::messages::to_json(j, camelize("stack_trace"), stack_trace);
 }
 
 std::string
diff --git a/go/messages.go b/go/messages.go
index 1f8c603f..e7dc6169 100644
--- a/go/messages.go
+++ b/go/messages.go
@@ -37,8 +37,9 @@ type Envelope struct {
 }
 
 type Exception struct {
-	Type    string `json:"type"`
-	Message string `json:"message,omitempty"`
+	Type       string `json:"type"`
+	Message    string `json:"message,omitempty"`
+	StackTrace string `json:"stackTrace,omitempty"`
 }
 
 type GherkinDocument struct {
diff --git a/java/src/generated/java/io/cucumber/messages/types/Exception.java b/java/src/generated/java/io/cucumber/messages/types/Exception.java
index d29a505a..f8396472 100644
--- a/java/src/generated/java/io/cucumber/messages/types/Exception.java
+++ b/java/src/generated/java/io/cucumber/messages/types/Exception.java
@@ -18,13 +18,16 @@
 public final class Exception {
     private final String type;
     private final String message;
+    private final String stackTrace;
 
     public Exception(
         String type,
-        String message
+        String message,
+        String stackTrace
     ) {
         this.type = requireNonNull(type, "Exception.type cannot be null");
         this.message = message;
+        this.stackTrace = stackTrace;
     }
 
     /**
@@ -41,6 +44,13 @@ public Optional<String> getMessage() {
         return Optional.ofNullable(message);
     }
 
+    /**
+      * The stringified stack trace of the exception that caused this result
+     */
+    public Optional<String> getStackTrace() {
+        return Optional.ofNullable(stackTrace);
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -48,14 +58,16 @@ public boolean equals(Object o) {
         Exception that = (Exception) o;
         return 
             type.equals(that.type) &&         
-            Objects.equals(message, that.message);        
+            Objects.equals(message, that.message) &&         
+            Objects.equals(stackTrace, that.stackTrace);        
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(
             type,
-            message
+            message,
+            stackTrace
         );
     }
 
@@ -64,6 +76,7 @@ public String toString() {
         return "Exception{" +
             "type=" + type +
             ", message=" + message +
+            ", stackTrace=" + stackTrace +
             '}';
     }
 }
diff --git a/java/src/main/java/io/cucumber/messages/Convertor.java b/java/src/main/java/io/cucumber/messages/Convertor.java
index 021e8fb8..a1677138 100644
--- a/java/src/main/java/io/cucumber/messages/Convertor.java
+++ b/java/src/main/java/io/cucumber/messages/Convertor.java
@@ -11,7 +11,7 @@ private Convertor(){
     }
 
     public static Exception toMessage(Throwable t) {
-        return new Exception(t.getClass().getName(), t.getMessage());
+        return new Exception(t.getClass().getName(), t.getMessage(), null);
     }
 
     public static Timestamp toMessage(java.time.Instant instant) {
diff --git a/javascript/src/messages.ts b/javascript/src/messages.ts
index 24f6122e..ceec6923 100644
--- a/javascript/src/messages.ts
+++ b/javascript/src/messages.ts
@@ -87,6 +87,8 @@ export class Exception {
   type: string = ''
 
   message?: string
+
+  stackTrace?: string
 }
 
 export class GherkinDocument {
diff --git a/jsonschema/Exception.json b/jsonschema/Exception.json
index a8187b58..b7d9d986 100644
--- a/jsonschema/Exception.json
+++ b/jsonschema/Exception.json
@@ -14,6 +14,10 @@
     "message": {
       "type": "string",
       "description": "The message of exception that caused this result. E.g. expected: \"a\" but was: \"b\""
+    },
+    "stackTrace": {
+      "type": "string",
+      "description": "The stringified stack trace of the exception that caused this result"
     }
   },
   "type": "object"
diff --git a/messages.md b/messages.md
index 685233d5..8183c829 100644
--- a/messages.md
+++ b/messages.md
@@ -51,6 +51,7 @@ will only have one of its fields set, which indicates the payload of the message
 | ----- | ---- | ----------- | ----------- |
 | `type` | string | yes | |
 | `message` | string | no | |
+| `stackTrace` | string | no | |
 
 ## GherkinDocument
 
diff --git a/perl/lib/Cucumber/Messages.pm b/perl/lib/Cucumber/Messages.pm
index 342db43e..5e5d51e8 100644
--- a/perl/lib/Cucumber/Messages.pm
+++ b/perl/lib/Cucumber/Messages.pm
@@ -546,6 +546,7 @@ use Scalar::Util qw( blessed );
 my %types = (
    type => 'string',
    message => 'string',
+   stack_trace => 'string',
 );
 
 # This is a work-around for the fact that Moo doesn't have introspection
@@ -580,6 +581,17 @@ has message =>
     );
 
 
+=head4 stack_trace
+
+The stringified stack trace of the exception that caused this result
+
+=cut
+
+has stack_trace =>
+    (is => 'ro',
+    );
+
+
 }
 
 package Cucumber::Messages::GherkinDocument {
diff --git a/php/src-generated/Exception.php b/php/src-generated/Exception.php
index dca44cac..ad21e051 100644
--- a/php/src-generated/Exception.php
+++ b/php/src-generated/Exception.php
@@ -35,6 +35,11 @@ public function __construct(
          * The message of exception that caused this result. E.g. expected: "a" but was: "b"
          */
         public readonly ?string $message = null,
+
+        /**
+         * The stringified stack trace of the exception that caused this result
+         */
+        public readonly ?string $stackTrace = null,
     ) {
     }
 
@@ -47,10 +52,12 @@ public static function fromArray(array $arr): self
     {
         self::ensureType($arr);
         self::ensureMessage($arr);
+        self::ensureStackTrace($arr);
 
         return new self(
             (string) $arr['type'],
             isset($arr['message']) ? (string) $arr['message'] : null,
+            isset($arr['stackTrace']) ? (string) $arr['stackTrace'] : null,
         );
     }
 
@@ -76,4 +83,14 @@ private static function ensureMessage(array $arr): void
             throw new SchemaViolationException('Property \'message\' was array');
         }
     }
+
+    /**
+     * @psalm-assert array{stackTrace?: string|int|bool} $arr
+     */
+    private static function ensureStackTrace(array $arr): void
+    {
+        if (array_key_exists('stackTrace', $arr) && is_array($arr['stackTrace'])) {
+            throw new SchemaViolationException('Property \'stackTrace\' was array');
+        }
+    }
 }
diff --git a/ruby/lib/cucumber/messages.deserializers.rb b/ruby/lib/cucumber/messages.deserializers.rb
index 3eacad5e..a5b26a65 100644
--- a/ruby/lib/cucumber/messages.deserializers.rb
+++ b/ruby/lib/cucumber/messages.deserializers.rb
@@ -104,6 +104,7 @@ def self.from_h(hash)
         self.new(
           type: hash[:type],
           message: hash[:message],
+          stack_trace: hash[:stackTrace],
         )
       end
     end
diff --git a/ruby/lib/cucumber/messages.dtos.rb b/ruby/lib/cucumber/messages.dtos.rb
index 55196e8c..5a70d4d6 100644
--- a/ruby/lib/cucumber/messages.dtos.rb
+++ b/ruby/lib/cucumber/messages.dtos.rb
@@ -229,12 +229,19 @@ class Exception < ::Cucumber::Messages::Message
       ##
       attr_reader :message
 
+      ##
+      # The stringified stack trace of the exception that caused this result
+      ##
+      attr_reader :stack_trace
+
       def initialize(
         type: '',
-        message: nil
+        message: nil,
+        stack_trace: nil
       )
         @type = type
         @message = message
+        @stack_trace = stack_trace
       end
     end