You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by fl...@apache.org on 2022/11/16 15:40:30 UTC

[tinkerpop] branch TINKERPOP-2348-2022 created (now c506f70878)

This is an automated email from the ASF dual-hosted git repository.

florianhockmann pushed a change to branch TINKERPOP-2348-2022
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


      at c506f70878 TINKERPOP-2348 Add nullable annotations

This branch includes the following new commits:

     new c506f70878 TINKERPOP-2348 Add nullable annotations

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tinkerpop] 01/01: TINKERPOP-2348 Add nullable annotations

Posted by fl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

florianhockmann pushed a commit to branch TINKERPOP-2348-2022
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit c506f7087862a12eb0a4138a31c9e2ead55f0bea
Author: Florian Hockmann <fh...@florian-hockmann.de>
AuthorDate: Wed Nov 2 17:17:25 2022 +0100

    TINKERPOP-2348 Add nullable annotations
    
    This only adds nullable annotations to the projects Gremlin.Net and the
    Gremlin.Net.Template, but not to the test projects.
    I intend to add it there in a follow-up PR to at least somehow limit
    the scope of this commit. This takes already care of everything
    user-facing.
    
    This unfortunately includes a few breaking changes (not necessarily
    complete):
    - Message types:
      * Some set property accessors removed
    - Structure types:
      * Some set property accessors removed
    - DefaultTraversal.Bytecode now abstract
    - GraphBinaryReader/Writer
      * ReadValueAsync / WriteValueAsync were split into two methods,
            for nullable and non-nullable values
    - Changed exceptions: Instead of NullReferenceExceptions,
        IOExceptions should be thrown during serialization
    
    Most of these breaking changes are also mentioned in the upgrade docs.
    I haven't added all of them there as I found it to be very unlikely that
    anyone is really affected by them.
---
 CHANGELOG.asciidoc                                 |   1 +
 docs/src/upgrade/release-3.7.x.asciidoc            |  31 ++-
 .../Gremlin.Net.Template.csproj                    |   1 +
 gremlin-dotnet/src/Gremlin.Net.Template/Service.cs |   2 +-
 .../src/Gremlin.Net/Driver/Connection.cs           |  18 +-
 .../src/Gremlin.Net/Driver/ConnectionFactory.cs    |   4 +-
 .../Driver/Exceptions/ConnectionClosedException.cs |  10 +-
 .../src/Gremlin.Net/Driver/GremlinClient.cs        |  30 +--
 .../Gremlin.Net/Driver/GremlinClientExtensions.cs  |  10 +-
 .../src/Gremlin.Net/Driver/GremlinServer.cs        |   6 +-
 .../src/Gremlin.Net/Driver/IMessageSerializer.cs   |   2 +-
 .../Gremlin.Net/Driver/Messages/ResponseMessage.cs |  25 ++-
 .../Gremlin.Net/Driver/Messages/ResponseResult.cs  |  21 +-
 .../Gremlin.Net/Driver/Messages/ResponseStatus.cs  |  28 ++-
 .../Driver/Remote/DriverRemoteConnection.cs        |  16 +-
 .../Driver/Remote/DriverRemoteTraversal.cs         |   5 +-
 .../ResponseHandlerForSingleRequestMessage.cs      |   6 +-
 .../src/Gremlin.Net/Driver/WebSocketConnection.cs  |   2 +-
 .../src/Gremlin.Net/Driver/WebSocketSettings.cs    |   2 +-
 gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj  |   5 +
 .../src/Gremlin.Net/Process/Traversal/Binding.cs   |  10 +-
 .../src/Gremlin.Net/Process/Traversal/Bindings.cs  |   9 +-
 .../src/Gremlin.Net/Process/Traversal/Bytecode.cs  |  24 ++-
 .../Process/Traversal/DefaultTraversal.cs          |  45 ++--
 .../Gremlin.Net/Process/Traversal/EnumWrapper.cs   |  11 +-
 .../Process/Traversal/GraphTraversal.cs            | 235 +++++++++++----------
 .../Process/Traversal/GraphTraversalSource.cs      |  87 ++++----
 .../Gremlin.Net/Process/Traversal/ITraversal.cs    |  12 +-
 .../Gremlin.Net/Process/Traversal/Instruction.cs   |  23 +-
 .../Process/Traversal/NamingConversions.cs         |  91 --------
 .../src/Gremlin.Net/Process/Traversal/P.cs         |  60 +++---
 .../Strategy/AbstractTraversalStrategy.cs          |   6 +-
 .../Strategy/Decoration/HaltedTraverserStrategy.cs |   2 +-
 .../Strategy/Decoration/PartitionStrategy.cs       |   4 +-
 .../Strategy/Decoration/SubgraphStrategy.cs        |   4 +-
 .../Strategy/Decoration/VertexProgramStrategy.cs   |   6 +-
 .../Strategy/Optimization/ProductiveByStrategy.cs  |   2 +-
 .../ReservedKeysVerificationStrategy.cs            |   2 +-
 .../src/Gremlin.Net/Process/Traversal/TextP.cs     |   7 +-
 .../Traversal/Translator/GroovyTranslator.cs       |   8 +-
 .../src/Gremlin.Net/Process/Traversal/Traverser.cs |   6 +-
 .../src/Gremlin.Net/Process/Traversal/__.cs        | 140 ++++++------
 gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs    |   2 +-
 gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs   |  10 +-
 .../src/Gremlin.Net/Structure/Element.cs           |  10 +-
 .../Structure/IO/GraphBinary/DataType.cs           |   4 +-
 .../IO/GraphBinary/GraphBinaryMessageSerializer.cs |   4 +-
 .../Structure/IO/GraphBinary/GraphBinaryReader.cs  |  30 ++-
 .../Structure/IO/GraphBinary/GraphBinaryWriter.cs  |  35 +--
 .../Structure/IO/GraphBinary/ITypeSerializer.cs    |  31 ++-
 .../IO/GraphBinary/RequestMessageSerializer.cs     |   8 +-
 .../IO/GraphBinary/ResponseMessageSerializer.cs    |  33 +--
 .../IO/GraphBinary/TypeSerializerRegistry.cs       |  33 ++-
 .../IO/GraphBinary/Types/ArraySerializer.cs        |   2 +-
 .../IO/GraphBinary/Types/BigDecimalSerializer.cs   |   9 +-
 .../IO/GraphBinary/Types/BigIntegerSerializer.cs   |   4 +-
 .../IO/GraphBinary/Types/BindingSerializer.cs      |   4 +-
 .../IO/GraphBinary/Types/BulkSetSerializer.cs      |   4 +-
 .../IO/GraphBinary/Types/ByteBufferSerializer.cs   |   4 +-
 .../IO/GraphBinary/Types/ByteCodeSerializer.cs     |  20 +-
 .../IO/GraphBinary/Types/ClassSerializer.cs        |   2 +-
 .../IO/GraphBinary/Types/CustomTypeSerializer.cs   |  14 +-
 .../IO/GraphBinary/Types/EdgeSerializer.cs         |  12 +-
 .../IO/GraphBinary/Types/EnumSerializer.cs         |   5 +-
 .../IO/GraphBinary/Types/LambdaSerializer.cs       |  12 +-
 .../IO/GraphBinary/Types/ListSerializer.cs         |  14 +-
 .../IO/GraphBinary/Types/MapSerializer.cs          |  15 +-
 .../Structure/IO/GraphBinary/Types/PSerializer.cs  |  24 ++-
 .../IO/GraphBinary/Types/PathSerializer.cs         |   7 +-
 .../IO/GraphBinary/Types/PropertySerializer.cs     |   7 +-
 .../IO/GraphBinary/Types/SetSerializer.cs          |   8 +-
 .../IO/GraphBinary/Types/SimpleTypeSerializer.cs   |  45 ++--
 .../IO/GraphBinary/Types/StringSerializer.cs       |   4 +-
 .../IO/GraphBinary/Types/TraversalSerializer.cs    |   2 +-
 .../Types/TraversalStrategySerializer.cs           |   4 +-
 .../IO/GraphBinary/Types/TraverserSerializer.cs    |   4 +-
 .../IO/GraphBinary/Types/TypeSerializer.cs         |   6 +-
 .../GraphBinary/Types/VertexPropertySerializer.cs  |   4 +-
 .../IO/GraphBinary/Types/VertexSerializer.cs       |   4 +-
 .../IO/GraphSON/BigIntegerDeserializer.cs          |   2 +
 .../Structure/IO/GraphSON/BulkSetSerializer.cs     |   2 +-
 .../IO/GraphSON/ByteBufferDeserializer.cs          |   4 +-
 .../Structure/IO/GraphSON/CharConverter.cs         |   3 +-
 .../Structure/IO/GraphSON/ClassSerializer.cs       |   4 +-
 .../Structure/IO/GraphSON/DecimalConverter.cs      |   5 +-
 .../Structure/IO/GraphSON/DirectionDeserializer.cs |   5 +-
 .../Structure/IO/GraphSON/DurationDeserializer.cs  |   5 +-
 .../IO/GraphSON/GraphSON2MessageSerializer.cs      |   2 +-
 .../IO/GraphSON/GraphSON3MessageSerializer.cs      |   2 +-
 .../IO/GraphSON/GraphSONMessageSerializer.cs       |  20 +-
 .../Structure/IO/GraphSON/GraphSONReader.cs        |  62 +++---
 .../Structure/IO/GraphSON/GraphSONWriter.cs        |  79 +++----
 .../Structure/IO/GraphSON/ListSerializer.cs        |   5 +-
 .../Structure/IO/GraphSON/MapSerializer.cs         |   4 +-
 .../Structure/IO/GraphSON/MergeDeserializer.cs     |   4 +-
 .../Structure/IO/GraphSON/NumberConverter.cs       |   2 +-
 .../Structure/IO/GraphSON/Path3Deserializer.cs     |   7 +-
 .../Structure/IO/GraphSON/PathDeserializer.cs      |   4 +-
 .../Structure/IO/GraphSON/PropertySerializer.cs    |  19 +-
 .../Structure/IO/GraphSON/SetSerializer.cs         |   2 +-
 .../Structure/IO/GraphSON/TDeserializer.cs         |   4 +-
 .../Structure/IO/GraphSON/UuidDeserializer.cs      |   3 +-
 .../IO/GraphSON/VertexPropertySerializer.cs        |   7 +-
 gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs   |  61 +++---
 .../src/Gremlin.Net/Structure/Property.cs          |  10 +-
 gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs |   2 +-
 .../src/Gremlin.Net/Structure/VertexProperty.cs    |   6 +-
 .../Process/Remote/RemoteStrategyTests.cs          |   2 +
 .../Gremlin.Net.UnitTest/Driver/ConnectionTests.cs |   6 +-
 .../Process/Traversal/TestTraversal.cs             |   2 +
 .../Structure/IO/GraphBinary/GraphBinaryTests.cs   |  21 +-
 .../Types/Sample/SamplePersonSerializer.cs         |  76 +++++--
 .../Types/Sample/SamplePersonSerializerTests.cs    |  28 ++-
 .../IO/GraphSON/BytecodeGraphSONSerializerTests.cs |   2 +
 114 files changed, 1039 insertions(+), 892 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 8c1278a47a..e523c7bc17 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -30,6 +30,7 @@ This release also includes changes from <<release-3-6-XXX, 3.6.XXX>>.
 * Added warning on vertex property cardinality mismatch when reading GraphML.
 * Bumped to `ws` 8.x for `gremlin-javascript`.
 * Added support for mid-traversal `E()`-steps to Gremlin core and GLV's.
+* Added nullable annotations to Gremlin.NET.
 
 [[release-3-6-2]]
 === TinkerPop 3.6.2 (Release Date: NOT OFFICIALLY RELEASED YET)
diff --git a/docs/src/upgrade/release-3.7.x.asciidoc b/docs/src/upgrade/release-3.7.x.asciidoc
index 239e3c9496..86719d9a1b 100644
--- a/docs/src/upgrade/release-3.7.x.asciidoc
+++ b/docs/src/upgrade/release-3.7.x.asciidoc
@@ -25,10 +25,21 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 *Release Date: NOT OFFICIALLY RELEASED YET*
 
-Please see the link:https://github.com/apache/tinkerpop/blob/3.7.0/CHANGELOG.asciidoc#release-3-7-0[changelog] for a complete list of all the modifications that are part of this release.
+Please see the link:https://github.com/apache/tinkerpop/blob/3.7.0/CHANGELOG.asciidoc#release-3-7-0[changelog] for acomplete list of all the modifications that are part of this release.
 
 === Upgrading for Users
 
+==== Gremlin.NET: Nullable Annotations
+
+Gremlin.NET now uses link:https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references#nullable-variable-annotations[nullable annotations]
+to state wether an argument or a return value can be null or not. This should make it much less likely to get a
+`NullReferenceException` from Gremlin.NET.
+
+This change required to make some breaking changes but most users should not be affected by this as the breaking
+changes are limited to APIs that are mostly intended for graph driver providers.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2348[TINKERPOP-2348]
+
 ==== Removed connectOnStartup javascript
 
 Removed the `connectOnStartup` option for Gremlin Javascript API to resolve potential `unhandledRejection` and race
@@ -43,4 +54,20 @@ const drc = new DriverRemoteConnection(url);
 drc.open().catch(err => {
    // Handle error upon open.
 })
-----
\ No newline at end of file
+----
+
+=== Upgrading for Graph Driver Providers
+
+==== Gremlin.NET: Nullable Reference Types
+
+Enabling nullable reference types comes with some breaking changes in Gremlin.NET which can affect driver providers.
+
+GraphBinary APIs changed to make better use of nullable reference types. Instead of one method `WriteValueAsync` and
+one method `ReadValueAsync`, there are now methods `WriteNullableValueAsync` and `ReadNullableValueAsync` that allow
+`null` values and methods `WriteNonNullableValueAsync` and `ReadNonNullableValueAsync` that do not allow `null` values.
+
+Some `set` property accessors were removed from some pure data classes in the `Structure` and the `Driver.Messages`
+namespaces to initialize these properties directly from the constructor which ensures that they are really not `null`.
+We also used this opportunity to convert some of these pure data classes into a `record`.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2348[TINKERPOP-2348]
diff --git a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
index 714ea7760b..753caa7131 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
@@ -20,6 +20,7 @@ limitations under the License.
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>    
diff --git a/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs b/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs
index 4ded6d3b83..d4ba4eb54e 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Template
             _g = g;
         }
 
-        public IList<string> FindCreatorsOfSoftware(string softwareName)
+        public IList<string?> FindCreatorsOfSoftware(string softwareName)
         {
             return _g.V().HasLabel("software").Has("name", softwareName).In("created").Values<string>("name").ToList();
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
index 223b979e28..4fb37351fd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
@@ -45,9 +45,9 @@ namespace Gremlin.Net.Driver
         private readonly IMessageSerializer _messageSerializer;
         private readonly Uri _uri;
         private readonly IWebSocketConnection _webSocketConnection;
-        private readonly string _username;
-        private readonly string _password;
-        private readonly string _sessionId;
+        private readonly string? _username;
+        private readonly string? _password;
+        private readonly string? _sessionId;
         private readonly bool _sessionEnabled;
 
         private readonly ConcurrentQueue<(RequestMessage msg, CancellationToken cancellationToken)> _writeQueue =
@@ -62,8 +62,8 @@ namespace Gremlin.Net.Driver
         private int _writeInProgress = 0;
         private const int Closed = 1;
 
-        public Connection(IWebSocketConnection webSocketConnection, Uri uri, string username, string password,
-            IMessageSerializer messageSerializer, string sessionId)
+        public Connection(IWebSocketConnection webSocketConnection, Uri uri, string? username, string? password,
+            IMessageSerializer messageSerializer, string? sessionId)
         {
             _uri = uri;
             _username = username;
@@ -132,7 +132,8 @@ namespace Gremlin.Net.Driver
             var receivedMsg = await _messageSerializer.DeserializeMessageAsync(received).ConfigureAwait(false);
             if (receivedMsg == null)
             {
-                ThrowMessageDeserializedNull();
+                throw new InvalidOperationException(
+                    "Received data deserialized into null object message. Cannot operate on it.");
             }
 
             try
@@ -149,9 +150,6 @@ namespace Gremlin.Net.Driver
             }
         }
 
-        private static void ThrowMessageDeserializedNull() =>
-            throw new InvalidOperationException("Received data deserialized into null object message. Cannot operate on it.");
-
         private void HandleReceivedMessage(ResponseMessage<List<object>> receivedMsg)
         {
             var status = receivedMsg.Status;
@@ -291,7 +289,7 @@ namespace Gremlin.Net.Driver
             {
                 msgBuilder.AddArgument(kv.Key, kv.Value);
             }
-            msgBuilder.AddArgument(Tokens.ArgsSession, _sessionId);
+            msgBuilder.AddArgument(Tokens.ArgsSession, _sessionId!);
             return msgBuilder.Create();
         }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs
index 3ccbc3c6a9..4657172d47 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs
@@ -27,11 +27,11 @@ namespace Gremlin.Net.Driver
     {
         private readonly WebSocketSettings _webSocketSettings;
         private readonly GremlinServer _gremlinServer;
-        private readonly string _sessionId;
+        private readonly string? _sessionId;
         private readonly IMessageSerializer _messageSerializer;
 
         public ConnectionFactory(GremlinServer gremlinServer, IMessageSerializer messageSerializer,
-            WebSocketSettings webSocketSettings, string sessionId)
+            WebSocketSettings webSocketSettings, string? sessionId)
         {
             _gremlinServer = gremlinServer;
             _messageSerializer = messageSerializer;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs
index 13417eabbe..e03c7f69a3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs
@@ -27,8 +27,8 @@ using System.Net.WebSockets;
 namespace Gremlin.Net.Driver.Exceptions
 {
     /// <summary>
-    ///     The exception that is thrown for requests that in-flight when the underlyingg websocket is closed by the server.
-    ///     Requests that recieve this exception will be in a non-deteministic state and may need to be retried.
+    ///     The exception that is thrown for requests that in-flight when the underlying websocket is closed by the server.
+    ///     Requests that receive this exception will be in a non-deterministic state and may need to be retried.
     /// </summary>
     /// <remarks>
     ///     It is recommended to use the same request retry policy that is applied when a <see cref="System.Net.WebSockets.WebSocketException" />,
@@ -44,19 +44,19 @@ namespace Gremlin.Net.Driver.Exceptions
         /// <summary>
         ///     Gets the Websocket closure description provided by the server.
         /// </summary>
-        public string Description { get; }
+        public string? Description { get; }
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="ConnectionClosedException" /> class.
         /// </summary>
-        public ConnectionClosedException(WebSocketCloseStatus? status, string description)
+        public ConnectionClosedException(WebSocketCloseStatus? status, string? description)
             : base(CreateMessage(status, description))
         {
             Status = status;
             Description = description;
         }
 
-        private static string CreateMessage(WebSocketCloseStatus? status, string description)
+        private static string CreateMessage(WebSocketCloseStatus? status, string? description)
         {
             return $"Connection closed by server. CloseStatus: {status?.ToString() ?? "<none>"}, CloseDescription: {description ?? "<none>"}." +
                 " Any in-progress requests on the connection will be in an unknown state, and may need to be retried.";
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
index acda9d04e6..7b306bd833 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
@@ -57,8 +57,8 @@ namespace Gremlin.Net.Driver
         /// <param name="sessionId">The session Id if Gremlin Client in session mode, defaults to null as session-less Client.</param>
         [Obsolete("This constructor is obsolete. Use the constructor that takes a IMessageSerializer instead.")]
         public GremlinClient(GremlinServer gremlinServer, GraphSONReader graphSONReader, GraphSONWriter graphSONWriter,
-            ConnectionPoolSettings connectionPoolSettings = null,
-            Action<ClientWebSocketOptions> webSocketConfiguration = null, string sessionId = null)
+            ConnectionPoolSettings? connectionPoolSettings = null,
+            Action<ClientWebSocketOptions>? webSocketConfiguration = null, string? sessionId = null)
             : this(gremlinServer, graphSONReader, graphSONWriter, SerializationTokens.GraphSON3MimeType,
                 connectionPoolSettings, webSocketConfiguration, sessionId)
         {
@@ -78,9 +78,9 @@ namespace Gremlin.Net.Driver
         /// </param>
         /// <param name="sessionId">The session Id if Gremlin Client in session mode, defaults to null as session-less Client.</param>
         [Obsolete("This constructor is obsolete. Use the constructor that takes a IMessageSerializer instead.")]
-        public GremlinClient(GremlinServer gremlinServer, GraphSONReader graphSONReader, GraphSONWriter graphSONWriter,
-            string mimeType, ConnectionPoolSettings connectionPoolSettings = null,
-            Action<ClientWebSocketOptions> webSocketConfiguration = null, string sessionId = null)
+        public GremlinClient(GremlinServer gremlinServer, GraphSONReader? graphSONReader, GraphSONWriter? graphSONWriter,
+            string mimeType, ConnectionPoolSettings? connectionPoolSettings = null,
+            Action<ClientWebSocketOptions>? webSocketConfiguration = null, string? sessionId = null)
         {
             IMessageSerializer messageSerializer;
             switch (mimeType)
@@ -91,8 +91,8 @@ namespace Gremlin.Net.Driver
                     VerifyGraphSONArgumentTypeForMimeType<GraphSON3Writer>(graphSONWriter, nameof(graphSONWriter),
                         mimeType);
                     messageSerializer = new GraphSON3MessageSerializer(
-                        (GraphSON3Reader) graphSONReader ?? new GraphSON3Reader(),
-                        (GraphSON3Writer) graphSONWriter ?? new GraphSON3Writer());
+                        (GraphSON3Reader?) graphSONReader ?? new GraphSON3Reader(),
+                        (GraphSON3Writer?) graphSONWriter ?? new GraphSON3Writer());
                     break;
                 case SerializationTokens.GraphSON2MimeType:
                     VerifyGraphSONArgumentTypeForMimeType<GraphSON2Reader>(graphSONReader, nameof(graphSONReader),
@@ -100,8 +100,8 @@ namespace Gremlin.Net.Driver
                     VerifyGraphSONArgumentTypeForMimeType<GraphSON2Writer>(graphSONWriter, nameof(graphSONWriter),
                         mimeType);
                     messageSerializer = new GraphSON2MessageSerializer(
-                        (GraphSON2Reader) graphSONReader ?? new GraphSON2Reader(),
-                        (GraphSON2Writer) graphSONWriter ?? new GraphSON2Writer());
+                        (GraphSON2Reader?) graphSONReader ?? new GraphSON2Reader(),
+                        (GraphSON2Writer?) graphSONWriter ?? new GraphSON2Writer());
                     break;
                 default:
                     throw new ArgumentException(nameof(mimeType), $"{mimeType} not supported");
@@ -131,10 +131,10 @@ namespace Gremlin.Net.Driver
                 connectionPoolSettings ?? new ConnectionPoolSettings(), LoggerFactory.CreateLogger<ConnectionPool>());
         }
 
-        private static void VerifyGraphSONArgumentTypeForMimeType<T>(object argument, string argumentName,
+        private static void VerifyGraphSONArgumentTypeForMimeType<T>(object? argument, string argumentName,
             string mimeType)
         {
-            if (argument != null && !(argument is T))
+            if (argument != null && argument is not T)
             {
                 throw new ArgumentException(
                     $"{argumentName} is not a {typeof(T).Name} but the mime type is: {mimeType}", argumentName);
@@ -164,10 +164,10 @@ namespace Gremlin.Net.Driver
         ///     that could potentially be controlled by an untrusted user.
         /// </param>
         /// <param name="loggerFactory">A factory to create loggers. If not provided, then nothing will be logged.</param>
-        public GremlinClient(GremlinServer gremlinServer, IMessageSerializer messageSerializer = null,
-            ConnectionPoolSettings connectionPoolSettings = null,
-            Action<ClientWebSocketOptions> webSocketConfiguration = null, string sessionId = null,
-            bool disableCompression = false, ILoggerFactory loggerFactory = null)
+        public GremlinClient(GremlinServer gremlinServer, IMessageSerializer? messageSerializer = null,
+            ConnectionPoolSettings? connectionPoolSettings = null,
+            Action<ClientWebSocketOptions>? webSocketConfiguration = null, string? sessionId = null,
+            bool disableCompression = false, ILoggerFactory? loggerFactory = null)
         {
             messageSerializer ??= new GraphBinaryMessageSerializer();
             var webSocketSettings = new WebSocketSettings
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs
index 54dabff4e8..8132c7ab55 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs
@@ -52,9 +52,9 @@ namespace Gremlin.Net.Driver
         ///     Thrown when a response is received from Gremlin Server that indicates
         ///     that an error occurred.
         /// </exception>
-        public static async Task<T> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
+        public static async Task<T?> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
             string requestScript,
-            Dictionary<string, object> bindings = null,
+            Dictionary<string, object>? bindings = null,
             CancellationToken cancellationToken = default)
         {
             var resultCollection = await gremlinClient.SubmitAsync<T>(requestScript, bindings, cancellationToken)
@@ -78,7 +78,7 @@ namespace Gremlin.Net.Driver
         ///     Thrown when a response is received from Gremlin Server that indicates
         ///     that an error occurred.
         /// </exception>
-        public static async Task<T> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
+        public static async Task<T?> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
             RequestMessage requestMessage, CancellationToken cancellationToken = default)
         {
             var resultCollection =
@@ -100,7 +100,7 @@ namespace Gremlin.Net.Driver
         ///     that an error occurred.
         /// </exception>
         public static async Task SubmitAsync(this IGremlinClient gremlinClient, string requestScript,
-            Dictionary<string, object> bindings = null, CancellationToken cancellationToken = default)
+            Dictionary<string, object>? bindings = null, CancellationToken cancellationToken = default)
         {
             await gremlinClient.SubmitAsync<object>(requestScript, bindings, cancellationToken).ConfigureAwait(false);
         }
@@ -138,7 +138,7 @@ namespace Gremlin.Net.Driver
         /// </exception>
         public static async Task<ResultSet<T>> SubmitAsync<T>(this IGremlinClient gremlinClient,
             string requestScript,
-            Dictionary<string, object> bindings = null,
+            Dictionary<string, object>? bindings = null,
             CancellationToken cancellationToken = default)
         {
             var msgBuilder = RequestMessage.Build(Tokens.OpsEval).AddArgument(Tokens.ArgsGremlin, requestScript);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs
index 43ef159e42..fbe5baef51 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs
@@ -39,7 +39,7 @@ namespace Gremlin.Net.Driver
         /// <param name="username">The username to submit on requests that require authentication.</param>
         /// <param name="password">The password to submit on requests that require authentication.</param>
         public GremlinServer(string hostname = "localhost", int port = 8182, bool enableSsl = false,
-            string username = null, string password = null)
+            string? username = null, string? password = null)
         {
             Uri = CreateUri(hostname, port, enableSsl);
             Username = username;
@@ -55,12 +55,12 @@ namespace Gremlin.Net.Driver
         /// <summary>
         ///     Gets the username to submit on requests that require authentication.
         /// </summary>
-        public string Username { get; }
+        public string? Username { get; }
 
         /// <summary>
         ///     Gets the password to submit on requests that require authentication.
         /// </summary>
-        public string Password { get; }
+        public string? Password { get; }
 
         private Uri CreateUri(string hostname, int port, bool enableSsl)
         {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs
index e1a6a0eca8..0f2d79fc60 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs
@@ -48,7 +48,7 @@ namespace Gremlin.Net.Driver
         /// <param name="message">The serialized message to deserialize.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The deserialized <see cref="ResponseMessage{T}"/>.</returns>
-        Task<ResponseMessage<List<object>>> DeserializeMessageAsync(byte[] message,
+        Task<ResponseMessage<List<object>>?> DeserializeMessageAsync(byte[] message,
             CancellationToken cancellationToken = default);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
index a273cc097b..bbb4c16ef1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
@@ -29,20 +29,33 @@ namespace Gremlin.Net.Driver.Messages
     ///     The message returned from the server.
     /// </summary>
     /// <typeparam name="T">The type of the data returned.</typeparam>
-    public class ResponseMessage<T>
+    public record ResponseMessage<T>
     {
         /// <summary>
-        ///     Gets or sets the identifier of the <see cref="RequestMessage"/> that generated this <see cref="ResponseMessage{T}"/>.
+        ///     Initializes a new instance of the <see cref="ResponseMessage{T}" /> record.
         /// </summary>
-        public Guid? RequestId { get; set; }
+        /// <param name="requestId">The identifier of the <see cref="RequestMessage"/> that generated this <see cref="ResponseMessage{T}"/>.</param>
+        /// <param name="status">Status information about this <see cref="ResponseMessage{T}"/>.</param>
+        /// <param name="result">The result with its data and optional meta information.</param>
+        public ResponseMessage(Guid? requestId, ResponseStatus status, ResponseResult<T> result)
+        {
+            RequestId = requestId;
+            Status = status;
+            Result = result;
+        }
+        
+        /// <summary>
+        ///     Gets the identifier of the <see cref="RequestMessage"/> that generated this <see cref="ResponseMessage{T}"/>.
+        /// </summary>
+        public Guid? RequestId { get; }
 
         /// <summary>
-        ///     Gets or sets status information about this <see cref="ResponseMessage{T}"/>.
+        ///     Gets status information about this <see cref="ResponseMessage{T}"/>.
         /// </summary>
-        public ResponseStatus Status { get; set; }
+        public ResponseStatus Status { get; }
 
         /// <summary>
-        ///     Gets or sets the result with its data and optional meta information.
+        ///     Gets the result with its data and optional meta information.
         /// </summary>
         public ResponseResult<T> Result { get; set; }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
index abc2907b76..387893a574 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
@@ -30,16 +30,27 @@ namespace Gremlin.Net.Driver.Messages
     ///     <see cref="ResponseMessage{T}"/> by the server.
     /// </summary>
     /// <typeparam name="T">The type of the <see cref="Data"/>.</typeparam>
-    public class ResponseResult<T>
+    public record ResponseResult<T>
     {
         /// <summary>
-        ///     Gets or sets the data of this result.
+        /// Initializes a new instance of the <see cref="ResponseResult{T}" /> record.
         /// </summary>
-        public T Data { get; set; }
+        /// <param name="data">The data of this result.</param>
+        /// <param name="meta">The (optional) meta data of this result.</param>
+        public ResponseResult(T? data, Dictionary<string, object>? meta = null)
+        {
+            Data = data;
+            Meta = meta ?? new Dictionary<string, object>();
+        }
+        
+        /// <summary>
+        ///     Gets the data of this result.
+        /// </summary>
+        public T? Data { get; }
 
         /// <summary>
-        ///     Gets or sets meta data of this result.
+        ///     Gets meta data of this result.
         /// </summary>
-        public Dictionary<string, object> Meta { get; set; }
+        public Dictionary<string, object> Meta { get; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
index 63530a38a3..1d361138ae 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
@@ -29,22 +29,36 @@ namespace Gremlin.Net.Driver.Messages
     /// <summary>
     ///     Represents status information of a <see cref="ResponseMessage{T}"/>.
     /// </summary>
-    public class ResponseStatus
+    public record ResponseStatus
     {
         /// <summary>
-        ///     Gets or sets the <see cref="ResponseStatusCode"/>.
+        ///     Initializes a new instance of the <see cref="ResponseStatus" /> record.
         /// </summary>
-        public ResponseStatusCode Code { get; set; }
+        /// <param name="code">The <see cref="ResponseStatusCode" />.</param>
+        /// <param name="attributes">The (optional) attributes with protocol-level information.</param>
+        /// <param name="message">The (optional) message which is just a human-readable string usually associated with errors.</param>
+        public ResponseStatus(ResponseStatusCode code, Dictionary<string, object>? attributes = null,
+            string? message = null)
+        {
+            Code = code;
+            Attributes = attributes ?? new Dictionary<string, object>();
+            Message = message;
+        }
+        
+        /// <summary>
+        ///     Gets the <see cref="ResponseStatusCode"/>.
+        /// </summary>
+        public ResponseStatusCode Code { get; }
 
         /// <summary>
-        ///     Gets or sets the attributes <see cref="Dictionary{TKey,TValue}"/> with protocol-level information.
+        ///     Gets the attributes <see cref="Dictionary{TKey,TValue}"/> with protocol-level information.
         /// </summary>
-        public Dictionary<string, object> Attributes { get; set; }
+        public Dictionary<string, object> Attributes { get; }
 
         /// <summary>
-        ///     Gets or sets the message which is just a human-readable string usually associated with errors.
+        ///     Gets the message which is just a human-readable string usually associated with errors.
         /// </summary>
-        public string Message { get; set; }
+        public string? Message { get; }
     }
 
     internal static class ResponseStatusExtensions
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
index 9e710ac2bc..36a33a727f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
@@ -54,7 +54,7 @@ namespace Gremlin.Net.Driver.Remote
             Tokens.RequestId, Tokens.ArgsUserAgent
         };
 
-        private readonly string _sessionId;
+        private readonly string? _sessionId;
         private string Processor => IsSessionBound ? Tokens.ProcessorSession : Tokens.ProcessorTraversal;
 
         /// <inheritdoc />
@@ -69,7 +69,7 @@ namespace Gremlin.Net.Driver.Remote
         /// <param name="loggerFactory">A factory to create loggers. If not provided, then nothing will be logged.</param>
         /// <exception cref="ArgumentNullException">Thrown when client is null.</exception>
         public DriverRemoteConnection(string host, int port, string traversalSource = "g",
-            ILoggerFactory loggerFactory = null) : this(
+            ILoggerFactory? loggerFactory = null) : this(
             new GremlinClient(new GremlinServer(host, port), loggerFactory: loggerFactory), traversalSource,
             logger: loggerFactory?.CreateLogger<DriverRemoteConnection>() ?? NullLogger<DriverRemoteConnection>.Instance)
         {
@@ -86,8 +86,8 @@ namespace Gremlin.Net.Driver.Remote
         {
         }
 
-        private DriverRemoteConnection(IGremlinClient client, string traversalSource, string sessionId = null,
-            ILogger<DriverRemoteConnection> logger = null)
+        private DriverRemoteConnection(IGremlinClient client, string traversalSource, string? sessionId = null,
+            ILogger<DriverRemoteConnection>? logger = null)
         {
             _client = client ?? throw new ArgumentNullException(nameof(client));
             _traversalSource = traversalSource ?? throw new ArgumentNullException(nameof(traversalSource));
@@ -115,7 +115,7 @@ namespace Gremlin.Net.Driver.Remote
         {
             var requestId = Guid.NewGuid();
             var resultSet = await SubmitBytecodeAsync(requestId, bytecode, cancellationToken).ConfigureAwait(false);
-            return new DriverRemoteTraversal<TStart, TEnd>(_client, requestId, resultSet);
+            return new DriverRemoteTraversal<TStart, TEnd>(resultSet);
         }
 
         private async Task<IEnumerable<Traverser>> SubmitBytecodeAsync(Guid requestid, Bytecode bytecode,
@@ -132,15 +132,15 @@ namespace Gremlin.Net.Driver.Remote
 
             if (IsSessionBound)
             {
-                requestMsg.AddArgument(Tokens.ArgsSession, _sessionId);
+                requestMsg.AddArgument(Tokens.ArgsSession, _sessionId!);
             }
 
             var optionsStrategyInst = bytecode.SourceInstructions.Find(
                 s => s.OperatorName == "withStrategies" && s.Arguments[0] is OptionsStrategy);
             if (optionsStrategyInst != null)
             {
-                OptionsStrategy optionsStrategy = optionsStrategyInst.Arguments[0];
-                foreach (KeyValuePair<string,dynamic> pair in optionsStrategy.Configuration)
+                OptionsStrategy optionsStrategy = optionsStrategyInst.Arguments[0]!;
+                foreach (var pair in optionsStrategy.Configuration)
                 {
                     if (_allowedKeys.Contains(pair.Key))
                     {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
index 6e610181ea..66501ffc34 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
@@ -29,10 +29,11 @@ namespace Gremlin.Net.Driver.Remote
 {
     internal class DriverRemoteTraversal<TStart, TEnd> : DefaultTraversal<TStart, TEnd>
     {
-        public DriverRemoteTraversal(IGremlinClient gremlinClient, Guid requestId,
-            IEnumerable<Traverser> traversers)
+        public DriverRemoteTraversal(IEnumerable<Traverser> traversers)
         {
             Traversers = traversers;
         }
+
+        public override Bytecode Bytecode => throw new NotSupportedException("Remote traversals do not have Bytecode");
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs
index 93b3097c58..7993ccb0a7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs
@@ -33,13 +33,13 @@ namespace Gremlin.Net.Driver
         public Task<ResultSet<T>> Result => _tcs.Task;
 
         private readonly TaskCompletionSource<ResultSet<T>> _tcs =
-            new TaskCompletionSource<ResultSet<T>>(TaskCreationOptions.RunContinuationsAsynchronously);
+            new(TaskCreationOptions.RunContinuationsAsynchronously);
         
-        private readonly List<T> _result = new List<T>();
+        private readonly List<T> _result = new();
 
         public void HandleReceived(ResponseMessage<List<object>> received)
         {
-            foreach (var d in received.Result.Data)
+            foreach (var d in received.Result.Data!)
             {
                 _result.Add((T) d);
             }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
index 5286409f3a..9aadcfe70a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
@@ -118,7 +118,7 @@ namespace Gremlin.Net.Driver
                     throw new ConnectionClosedException(received.CloseStatus, received.CloseStatusDescription);
                 }
 
-                ms.Write(receiveBuffer.Array, receiveBuffer.Offset, received.Count);
+                ms.Write(receiveBuffer.Array!, receiveBuffer.Offset, received.Count);
             } while (!received.EndOfMessage);
 
             return ms.ToArray();
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
index 5e7722a154..770d7c620e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
@@ -39,7 +39,7 @@ namespace Gremlin.Net.Driver
         ///     Gets or sets the delegate that will be invoked with the <see cref="ClientWebSocketOptions" />
         ///     object used to configure WebSocket connections.
         /// </summary>
-        public Action<ClientWebSocketOptions> WebSocketConfigurationCallback { get; set; }
+        public Action<ClientWebSocketOptions>? WebSocketConfigurationCallback { get; set; }
 
 #if NET6_0_OR_GREATER
         /// <summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj b/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
index 3af2081a11..e91a041a14 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
+++ b/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
@@ -22,6 +22,7 @@ limitations under the License.
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <LangVersion>9</LangVersion>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <PropertyGroup Label="Package">
@@ -79,6 +80,10 @@ NOTE that versions suffixed with "-rc" are considered release candidates (i.e. p
     
   <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
     <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
+    <PackageReference Include="Nullable" Version="1.3.1">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs
index 80c826930f..ce76181f95 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         /// <param name="key">The key that identifies the <see cref="Binding" />.</param>
         /// <param name="value">The value of the <see cref="Binding" />.</param>
-        public Binding(string key, object value)
+        public Binding(string key, object? value)
         {
             Key = key;
             Value = value;
@@ -49,18 +49,18 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets the value of the <see cref="Binding" />.
         /// </summary>
-        public object Value { get; }
+        public object? Value { get; }
 
         /// <inheritdoc />
-        public bool Equals(Binding other)
+        public bool Equals(Binding? other)
         {
             if (other == null)
                 return false;
-            return Key == other.Key && Value.Equals(other.Value);
+            return Key == other.Key && (Value?.Equals(other.Value) ?? other.Value == null);
         }
 
         /// <inheritdoc />
-        public override bool Equals(object other)
+        public override bool Equals(object? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs
index a6e13b9ec0..746b4994c3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs
@@ -34,10 +34,9 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets an instance of the <see cref="Bindings" /> class.
         /// </summary>
-        public static Bindings Instance { get; } = new Bindings();
+        public static Bindings Instance { get; } = new();
 
-        private static readonly ThreadLocal<Dictionary<object, string>> BoundVariableByValue =
-            new ThreadLocal<Dictionary<object, string>>();
+        private static readonly ThreadLocal<Dictionary<object, string>> BoundVariableByValue = new();
 
         /// <summary>
         ///     Binds the variable to the specified value.
@@ -45,7 +44,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <param name="variable">The variable to bind.</param>
         /// <param name="value">The value to which the variable should be bound.</param>
         /// <returns>The bound value.</returns>
-        public TV Of<TV>(string variable, TV value)
+        public TV Of<TV>(string variable, TV value) where TV : notnull
         {
             var dict = BoundVariableByValue.Value;
             if (dict == null)
@@ -57,7 +56,7 @@ namespace Gremlin.Net.Process.Traversal
             return value;
         }
 
-        internal static string GetBoundVariable<TV>(TV value)
+        internal static string? GetBoundVariable<TV>(TV value) where TV : notnull
         {
             var dict = BoundVariableByValue.Value;
             if (dict == null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
index e692ed23e2..604ba6749e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 
 namespace Gremlin.Net.Process.Traversal
@@ -60,19 +61,19 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets the traversal source instructions.
         /// </summary>
-        public List<Instruction> SourceInstructions { get; } = new List<Instruction>();
+        public List<Instruction> SourceInstructions { get; } = new();
 
         /// <summary>
         ///     Gets the <see cref="ITraversal" /> instructions.
         /// </summary>
-        public List<Instruction> StepInstructions { get; } = new List<Instruction>();
+        public List<Instruction> StepInstructions { get; } = new();
 
         /// <summary>
         ///     Add a traversal source instruction to the bytecode.
         /// </summary>
         /// <param name="sourceName">The traversal source method name (e.g. withSack()).</param>
         /// <param name="args">The traversal source method arguments.</param>
-        public void AddSource(string sourceName, params object[] args)
+        public void AddSource(string sourceName, params object?[] args)
         {
             SourceInstructions.Add(new Instruction(sourceName, FlattenArguments(args)));
             Bindings.Clear();
@@ -83,17 +84,17 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         /// <param name="stepName">The traversal method name (e.g. out()).</param>
         /// <param name="args">The traversal method arguments.</param>
-        public void AddStep(string stepName, params object[] args)
+        public void AddStep(string stepName, params object?[] args)
         {
             StepInstructions.Add(new Instruction(stepName, FlattenArguments(args)));
             Bindings.Clear();
         }
 
-        private object[] FlattenArguments(object[] arguments)
+        private object?[] FlattenArguments(object?[] arguments)
         {
             if (arguments.Length == 0)
                 return EmptyArray;
-            var flatArguments = new List<object>();
+            var flatArguments = new List<object?>();
             foreach (var arg in arguments)
             {
                 if (arg is object[] objects)
@@ -108,7 +109,8 @@ namespace Gremlin.Net.Process.Traversal
             return flatArguments.ToArray();
         }
 
-        private object ConvertArgument(object argument, bool searchBindings)
+        [return: NotNullIfNotNull("argument")]
+        private object? ConvertArgument(object? argument, bool searchBindings)
         {
             if (null == argument)
             {
@@ -129,7 +131,7 @@ namespace Gremlin.Net.Process.Traversal
             
             if (IsDictionaryType(argument.GetType()))
             {
-                var dict = new Dictionary<object, object>();
+                var dict = new Dictionary<object, object?>();
                 foreach (DictionaryEntry item in (IDictionary)argument)
                 {
                     dict[ConvertArgument(item.Key, true)] = ConvertArgument(item.Value, true);
@@ -138,13 +140,13 @@ namespace Gremlin.Net.Process.Traversal
             }
             if (IsListType(argument.GetType()))
             {
-                var list = new List<object>(((IList) argument).Count);
-                list.AddRange(from object item in (IList) argument select ConvertArgument(item, true));
+                var list = new List<object?>(((IList) argument).Count);
+                list.AddRange(from object? item in (IList)argument select ConvertArgument(item, true));
                 return list;
             }
             if (IsHashSetType(argument.GetType()))
             {
-                var set = new HashSet<object>();
+                var set = new HashSet<object?>();
                 foreach (var item in (IEnumerable)argument)
                 {
                     set.Add(ConvertArgument(item, true));
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
index 6ca2b0c2d3..d2da68e703 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
@@ -35,12 +36,12 @@ namespace Gremlin.Net.Process.Traversal
     /// </summary>
     public abstract class DefaultTraversal<TStart, TEnd> : ITraversal<TStart, TEnd>
     {
-        private IEnumerator<Traverser> _traverserEnumerator;
+        private IEnumerator<Traverser>? _traverserEnumerator;
 
         /// <summary>
         ///     Gets the <see cref="Traversal.Bytecode" /> representation of this traversal.
         /// </summary>
-        public Bytecode Bytecode { get; protected set; }
+        public abstract Bytecode Bytecode { get; }
         
         /// <summary>
         ///     Determines if this traversal was spawned anonymously or not.
@@ -50,7 +51,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal.
         /// </summary>
-        public IEnumerable<Traverser> Traversers { get; set; }
+        public IEnumerable<Traverser>? Traversers { get; set; }
 
         ITraversal ITraversal.Iterate()
         {
@@ -63,7 +64,7 @@ namespace Gremlin.Net.Process.Traversal
         protected ICollection<ITraversalStrategy> TraversalStrategies { get; set; } = new List<ITraversalStrategy>();
 
         private IEnumerator<Traverser> TraverserEnumerator
-            => _traverserEnumerator ?? (_traverserEnumerator = GetTraverserEnumerator());
+            => _traverserEnumerator ??= GetTraverserEnumerator();
 
         private bool _nextAvailable;
         private bool _fetchedNext;
@@ -109,23 +110,23 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <inheritdoc />
-        public TEnd Current => GetCurrent<TEnd>();
+        public TEnd? Current => GetCurrent<TEnd>();
 
-        object IEnumerator.Current => GetCurrent();
+        object? IEnumerator.Current => GetCurrent();
 
-        private TReturn GetCurrent<TReturn>()
+        private TReturn? GetCurrent<TReturn>()
         {
             var value = GetCurrent();
             var returnType = typeof(TReturn);
             if (value == null || value.GetType() == returnType)
             {
                 // Avoid evaluating type comparisons
-                return (TReturn) value;
+                return (TReturn?) value;
             }
             return (TReturn) GetValue(returnType, value);
         }
 
-        private object GetCurrent()
+        private object? GetCurrent()
         {
             // Use dynamic to object to prevent runtime dynamic conversion evaluation
             return TraverserEnumerator.Current?.Object;
@@ -134,7 +135,8 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         /// Gets the value, converting to the expected type when necessary and supported. 
         /// </summary>
-        private static object GetValue(Type type, object value)
+        [return: NotNullIfNotNull("value")]
+        private static object? GetValue(Type type, object? value)
         {
             var genericType = type.GetTypeInfo().IsGenericType
                 ? type.GetTypeInfo().GetGenericTypeDefinition()
@@ -144,7 +146,8 @@ namespace Gremlin.Net.Process.Traversal
                 var keyType = type.GenericTypeArguments[0];
                 var valueType = type.GenericTypeArguments[1];
                 var mapType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
-                var result = (IDictionary) Activator.CreateInstance(mapType);
+                var result = (IDictionary?)Activator.CreateInstance(mapType) ??
+                             throw new InvalidOperationException($"Cannot convert value {value} to a Dictionary.");
                 foreach (DictionaryEntry kv in dictValue)
                 {
                     result.Add(GetValue(keyType, kv.Key), GetValue(valueType, kv.Value));
@@ -155,7 +158,8 @@ namespace Gremlin.Net.Process.Traversal
             {
                 var childType = type.GenericTypeArguments[0];
                 var listType = typeof(List<>).MakeGenericType(childType);
-                var result = (IList) Activator.CreateInstance(listType);
+                var result = (IList?)Activator.CreateInstance(listType) ??
+                             throw new InvalidOperationException($"Cannot convert value {value} to a list.");
                 foreach (var itemValue in enumerableValue)
                 {
                     result.Add(itemValue);
@@ -169,6 +173,11 @@ namespace Gremlin.Net.Process.Traversal
         {
             if (Traversers == null)
                 ApplyStrategies();
+            if (Traversers == null)
+            {
+                throw new InvalidOperationException(
+                    $"Cannot enumerate the traversal as there are no {nameof(Traversers)}. Maybe a strategy needs to be added.");
+            }
             return Traversers.GetEnumerator();
         }
 
@@ -196,7 +205,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Gets the next result from the traversal.
         /// </summary>
         /// <returns>The result.</returns>
-        public TEnd Next()
+        public TEnd? Next()
         {
             MoveNext();
             return Current;
@@ -207,7 +216,7 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         /// <param name="amount">The number of results to get.</param>
         /// <returns>The n-results.</returns>
-        public IEnumerable<TEnd> Next(int amount)
+        public IEnumerable<TEnd?> Next(int amount)
         {
             for (var i = 0; i < amount; i++)
                 yield return Next();
@@ -240,9 +249,9 @@ namespace Gremlin.Net.Process.Traversal
         ///     Puts all the results into a <see cref="List{T}" />.
         /// </summary>
         /// <returns>The results in a list.</returns>
-        public IList<TEnd> ToList()
+        public IList<TEnd?> ToList()
         {
-            var objs = new List<TEnd>();
+            var objs = new List<TEnd?>();
             while (MoveNext())
                 objs.Add(Current);
             return objs;
@@ -252,9 +261,9 @@ namespace Gremlin.Net.Process.Traversal
         ///     Puts all the results into a <see cref="HashSet{T}" />.
         /// </summary>
         /// <returns>The results in a set.</returns>
-        public ISet<TEnd> ToSet()
+        public ISet<TEnd?> ToSet()
         {
-            var objs = new HashSet<TEnd>();
+            var objs = new HashSet<TEnd?>();
             while (MoveNext())
                 objs.Add(Current);
             return objs;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs
index ac0185cc4a..3df6a6da29 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs
@@ -47,12 +47,12 @@ namespace Gremlin.Net.Process.Traversal
         /// <param name="enumValue">The value of the enum.</param>
         protected EnumWrapper(string enumName, string enumValue)
         {
-            EnumName = enumName;
-            EnumValue = enumValue;
+            EnumName = enumName ?? throw new ArgumentNullException(nameof(enumName));
+            EnumValue = enumValue ?? throw new ArgumentNullException(nameof(enumValue));
         }
 
         /// <inheritdoc />
-        public bool Equals(EnumWrapper other)
+        public bool Equals(EnumWrapper? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -60,7 +60,7 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -73,8 +73,7 @@ namespace Gremlin.Net.Process.Traversal
         {
             unchecked
             {
-                return ((EnumName != null ? EnumName.GetHashCode() : 0) * 397) ^
-                       (EnumValue != null ? EnumValue.GetHashCode() : 0);
+                return (EnumName.GetHashCode() * 397) ^ EnumValue.GetHashCode();
             }
         }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 62ba569137..f4ffb36ecd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -64,11 +64,14 @@ namespace Gremlin.Net.Process.Traversal
             IsAnonymous = anonymous;
         }
 
+        /// <inheritdoc />
+        public override Bytecode Bytecode { get; }
+
         private static GraphTraversal<TNewStart, TNewEnd> Wrap<TNewStart, TNewEnd>(GraphTraversal<TStart, TEnd> traversal)
         {
             if (typeof(TNewStart) == typeof(TStart) && typeof(TNewEnd) == typeof(TEnd))
             {
-                return traversal as GraphTraversal<TNewStart, TNewEnd>;
+                return (traversal as GraphTraversal<TNewStart, TNewEnd>)!;
             }
             // New wrapper
             return new GraphTraversal<TNewStart, TNewEnd>(traversal.TraversalStrategies, traversal.Bytecode, traversal.IsAnonymous);
@@ -78,15 +81,15 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the V step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> V (params object[] vertexIdsOrElements)
+        public GraphTraversal<TStart, Vertex> V (params object?[]? vertexIdsOrElements)
         {
             if (vertexIdsOrElements == null)
             {
-                Bytecode.AddStep("V", new object[] { null });
+                Bytecode.AddStep("V", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(vertexIdsOrElements.Length);
+                var args = new List<object?>(vertexIdsOrElements.Length);
                 args.AddRange(vertexIdsOrElements);
                 Bytecode.AddStep("V", args.ToArray());
             }
@@ -96,15 +99,15 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the E step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> E (params object[] edgeIdsOrElements)
+        public GraphTraversal<TStart, Edge> E (params object?[]? edgeIdsOrElements)
         {
             if (edgeIdsOrElements == null)
             {
-                Bytecode.AddStep("E", new object[] { null });
+                Bytecode.AddStep("E", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(edgeIdsOrElements.Length);
+                var args = new List<object?>(edgeIdsOrElements.Length);
                 args.AddRange(edgeIdsOrElements);
                 Bytecode.AddStep("E", args.ToArray());
             }
@@ -231,11 +234,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the both step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> Both (params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> Both (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("both", args.ToArray());
             return Wrap<TStart, Vertex>(this);
@@ -244,11 +247,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the bothE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> BothE (params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> BothE (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("bothE", args.ToArray());
             return Wrap<TStart, Edge>(this);
@@ -266,7 +269,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the branch step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Branch<TNewEnd> (IFunction function)
+        public GraphTraversal<TStart, TNewEnd> Branch<TNewEnd> (IFunction? function)
         {
             Bytecode.AddStep("branch", function);
             return Wrap<TStart, TNewEnd>(this);
@@ -329,7 +332,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> By (string key)
+        public GraphTraversal<TStart, TEnd> By (string? key)
         {
             Bytecode.AddStep("by", key);
             return Wrap<TStart, TEnd>(this);
@@ -338,7 +341,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> By (string key, IComparator comparator)
+        public GraphTraversal<TStart, TEnd> By (string? key, IComparator comparator)
         {
             Bytecode.AddStep("by", key, comparator);
             return Wrap<TStart, TEnd>(this);
@@ -374,7 +377,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string service)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string? service)
         {
             Bytecode.AddStep("call", service);
             return Wrap<TStart, TNewEnd>(this);
@@ -383,7 +386,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string service, ITraversal t)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string? service, ITraversal? t)
         {
             Bytecode.AddStep("call", service, t);
             return Wrap<TStart, TNewEnd>(this);
@@ -392,7 +395,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string service, IDictionary<object,object> m)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string? service, IDictionary<object,object>? m)
         {
             Bytecode.AddStep("call", service, m);
             return Wrap<TStart, TNewEnd>(this);
@@ -401,7 +404,8 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string service, IDictionary<object,object> m, ITraversal t)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd>(string? service, IDictionary<object, object>? m,
+            ITraversal? t)
         {
             Bytecode.AddStep("call", service, m, t);
             return Wrap<TStart, TNewEnd>(this);
@@ -545,11 +549,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the dedup step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Dedup (Scope scope, params string[] dedupLabels)
+        public GraphTraversal<TStart, TEnd> Dedup (Scope scope, params string?[] dedupLabels)
         {
             if (dedupLabels == null) throw new ArgumentNullException(nameof(dedupLabels));
 
-            var args = new List<object>(1 + dedupLabels.Length) { scope };
+            var args = new List<object?>(1 + dedupLabels.Length) { scope };
             args.AddRange(dedupLabels);
             Bytecode.AddStep("dedup", args.ToArray());
             return Wrap<TStart, TEnd>(this);
@@ -558,11 +562,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the dedup step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Dedup (params string[] dedupLabels)
+        public GraphTraversal<TStart, TEnd> Dedup (params string?[] dedupLabels)
         {
             if (dedupLabels == null) throw new ArgumentNullException(nameof(dedupLabels));
 
-            var args = new List<object>(dedupLabels.Length);
+            var args = new List<object?>(dedupLabels.Length);
             args.AddRange(dedupLabels);
             Bytecode.AddStep("dedup", args.ToArray());
             return Wrap<TStart, TEnd>(this);
@@ -589,11 +593,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the elementMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, IDictionary<object, TNewEnd>> ElementMap<TNewEnd> (params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<object, TNewEnd>> ElementMap<TNewEnd> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(0 + propertyKeys.Length);
+            var args = new List<object?>(0 + propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("elementMap", args.ToArray());
             return Wrap<TStart, IDictionary<object, TNewEnd>>(this);
@@ -638,7 +642,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the fail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Fail (string msg)
+        public GraphTraversal<TStart, TEnd> Fail (string? msg)
         {
             Bytecode.AddStep("fail", msg);
             return Wrap<TStart, TEnd>(this);
@@ -647,7 +651,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the fail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Fail (string msg, IDictionary<string,object> m)
+        public GraphTraversal<TStart, TEnd> Fail (string? msg, IDictionary<string,object> m)
         {
             Bytecode.AddStep("fail", msg, m);
             return Wrap<TStart, TEnd>(this);
@@ -656,7 +660,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the filter step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Filter (IPredicate predicate)
+        public GraphTraversal<TStart, TEnd> Filter (IPredicate? predicate)
         {
             Bytecode.AddStep("filter", predicate);
             return Wrap<TStart, TEnd>(this);
@@ -674,7 +678,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the flatMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> FlatMap<TNewEnd> (IFunction function)
+        public GraphTraversal<TStart, TNewEnd> FlatMap<TNewEnd> (IFunction? function)
         {
             Bytecode.AddStep("flatMap", function);
             return Wrap<TStart, TNewEnd>(this);
@@ -701,7 +705,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the fold step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Fold<TNewEnd> (TNewEnd seed, IBiFunction foldFunction)
+        public GraphTraversal<TStart, TNewEnd> Fold<TNewEnd> (TNewEnd seed, IBiFunction? foldFunction)
         {
             Bytecode.AddStep("fold", seed, foldFunction);
             return Wrap<TStart, TNewEnd>(this);
@@ -710,7 +714,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the from step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> From (string fromStepLabel)
+        public GraphTraversal<TStart, TEnd> From (string? fromStepLabel)
         {
             Bytecode.AddStep("from", fromStepLabel);
             return Wrap<TStart, TEnd>(this);
@@ -773,7 +777,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (string propertyKey)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey)
         {
             Bytecode.AddStep("has", propertyKey);
             return Wrap<TStart, TEnd>(this);
@@ -782,7 +786,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (string propertyKey, object value)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey, object? value)
         {
             Bytecode.AddStep("has", propertyKey, value);
             return Wrap<TStart, TEnd>(this);
@@ -791,7 +795,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (string propertyKey, P predicate)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey, P? predicate)
         {
             Bytecode.AddStep("has", propertyKey, predicate);
             return Wrap<TStart, TEnd>(this);
@@ -800,7 +804,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (string label, string propertyKey, object value)
+        public GraphTraversal<TStart, TEnd> Has (string? label, string? propertyKey, object? value)
         {
             Bytecode.AddStep("has", label, propertyKey, value);
             return Wrap<TStart, TEnd>(this);
@@ -809,7 +813,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (string label, string propertyKey, P predicate)
+        public GraphTraversal<TStart, TEnd> Has (string? label, string? propertyKey, P? predicate)
         {
             Bytecode.AddStep("has", label, propertyKey, predicate);
             return Wrap<TStart, TEnd>(this);
@@ -818,7 +822,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (string propertyKey, ITraversal propertyTraversal)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey, ITraversal propertyTraversal)
         {
             Bytecode.AddStep("has", propertyKey, propertyTraversal);
             return Wrap<TStart, TEnd>(this);
@@ -827,7 +831,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (T accessor, object value)
+        public GraphTraversal<TStart, TEnd> Has (T accessor, object? value)
         {
             Bytecode.AddStep("has", accessor, value);
             return Wrap<TStart, TEnd>(this);
@@ -836,7 +840,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Has (T accessor, P predicate)
+        public GraphTraversal<TStart, TEnd> Has (T accessor, P? predicate)
         {
             Bytecode.AddStep("has", accessor, predicate);
             return Wrap<TStart, TEnd>(this);
@@ -854,16 +858,16 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasId step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasId (object id, params object[] otherIds)
+        public GraphTraversal<TStart, TEnd> HasId (object? id, params object?[]? otherIds)
         {
-            List<object> args;
+            List<object?> args;
             if (otherIds == null)
             {
-                args = new List<object> { id, null };
+                args = new List<object?> { id, null };
             }
             else
             {
-                args = new List<object>(1 + otherIds.Length) { id };
+                args = new List<object?>(1 + otherIds.Length) { id };
                 args.AddRange(otherIds);
             }
             Bytecode.AddStep("hasId", args.ToArray());
@@ -873,7 +877,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasId step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasId (P predicate)
+        public GraphTraversal<TStart, TEnd> HasId (P? predicate)
         {
             Bytecode.AddStep("hasId", predicate);
             return Wrap<TStart, TEnd>(this);
@@ -882,7 +886,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasKey step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasKey (P predicate)
+        public GraphTraversal<TStart, TEnd> HasKey (P? predicate)
         {
             Bytecode.AddStep("hasKey", predicate);
             return Wrap<TStart, TEnd>(this);
@@ -891,16 +895,16 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasKey step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasKey (string label, params string[] otherLabels)
+        public GraphTraversal<TStart, TEnd> HasKey (string? label, params string?[]? otherLabels)
         {
-            List<object> args;
+            List<object?> args;
             if (otherLabels == null)
             {
-                args = new List<object> { label, null };
+                args = new List<object?> { label, null };
             }
             else
             {
-                args = new List<object>(1 + otherLabels.Length) { label };
+                args = new List<object?>(1 + otherLabels.Length) { label };
                 args.AddRange(otherLabels);
             }
             Bytecode.AddStep("hasKey", args.ToArray());
@@ -910,7 +914,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasLabel step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasLabel (P predicate)
+        public GraphTraversal<TStart, TEnd> HasLabel (P? predicate)
         {
             Bytecode.AddStep("hasLabel", predicate);
             return Wrap<TStart, TEnd>(this);
@@ -919,16 +923,16 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasLabel step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasLabel (string label, params string[] otherLabels)
+        public GraphTraversal<TStart, TEnd> HasLabel (string? label, params string?[]? otherLabels)
         {
-            List<object> args;
+            List<object?> args;
             if (otherLabels == null)
             {
-                args = new List<object> { label, null };
+                args = new List<object?> { label, null };
             }
             else
             {
-                args = new List<object>(1 + otherLabels.Length) { label };
+                args = new List<object?>(1 + otherLabels.Length) { label };
                 args.AddRange(otherLabels);
             }
             Bytecode.AddStep("hasLabel", args.ToArray());
@@ -938,7 +942,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasNot step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasNot (string propertyKey)
+        public GraphTraversal<TStart, TEnd> HasNot (string? propertyKey)
         {
             Bytecode.AddStep("hasNot", propertyKey);
             return Wrap<TStart, TEnd>(this);
@@ -947,16 +951,16 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasValue step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasValue (object value, params object[] otherValues)
+        public GraphTraversal<TStart, TEnd> HasValue (object? value, params object?[]? otherValues)
         {
-            List<object> args;
+            List<object?> args;
             if (otherValues == null)
             {
-                args = new List<object> { value, null };
+                args = new List<object?> { value, null };
             }
             else
             {
-                args = new List<object>(1 + otherValues.Length) { value };
+                args = new List<object?>(1 + otherValues.Length) { value };
                 args.AddRange(otherValues);
             }
             Bytecode.AddStep("hasValue", args.ToArray());
@@ -966,7 +970,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the hasValue step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> HasValue (P predicate)
+        public GraphTraversal<TStart, TEnd> HasValue (P? predicate)
         {
             Bytecode.AddStep("hasValue", predicate);
             return Wrap<TStart, TEnd>(this);
@@ -993,11 +997,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the in step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> In (params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> In (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("in", args.ToArray());
             return Wrap<TStart, Vertex>(this);
@@ -1006,11 +1010,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the inE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> InE (params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> InE (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("inE", args.ToArray());
             return Wrap<TStart, Edge>(this);
@@ -1037,17 +1041,17 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the inject step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Inject (params TEnd[] injections)
+        public GraphTraversal<TStart, TEnd> Inject (params TEnd?[]? injections)
         {
             // null injections is treated as g.inject(null) meaning inject a single null traverser
             if (injections == null)
             {
-                Bytecode.AddStep("inject", new object[] { null });
+                Bytecode.AddStep("inject", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(injections.Length);
-                args.AddRange(injections.Cast<object>());
+                var args = new List<object?>(injections.Length);
+                args.AddRange(injections.Cast<object?>());
                 Bytecode.AddStep("inject", args.ToArray());
             }
 
@@ -1057,7 +1061,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the is step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Is (object value)
+        public GraphTraversal<TStart, TEnd> Is (object? value)
         {
             Bytecode.AddStep("is", value);
             return Wrap<TStart, TEnd>(this);
@@ -1066,7 +1070,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the is step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Is (P predicate)
+        public GraphTraversal<TStart, TEnd> Is (P? predicate)
         {
             Bytecode.AddStep("is", predicate);
             return Wrap<TStart, TEnd>(this);
@@ -1129,7 +1133,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the loops step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, int> Loops (string loopName)
+        public GraphTraversal<TStart, int> Loops (string? loopName)
         {
             Bytecode.AddStep("loops", loopName);
             return Wrap<TStart, int>(this);
@@ -1138,7 +1142,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the map step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Map<TNewEnd> (IFunction function)
+        public GraphTraversal<TStart, TNewEnd> Map<TNewEnd> (IFunction? function)
         {
             Bytecode.AddStep("map", function);
             return Wrap<TStart, TNewEnd>(this);
@@ -1223,7 +1227,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> MergeE (IDictionary<object,object> m)
+        public GraphTraversal<TStart, Edge> MergeE (IDictionary<object,object>? m)
         {
             Bytecode.AddStep("mergeE", m);
             return Wrap<TStart, Edge>(this);
@@ -1232,7 +1236,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> MergeE (ITraversal t)
+        public GraphTraversal<TStart, Edge> MergeE (ITraversal? t)
         {
             Bytecode.AddStep("mergeE", t);
             return Wrap<TStart, Edge>(this);
@@ -1250,7 +1254,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> MergeV (IDictionary<object,object> m)
+        public GraphTraversal<TStart, Vertex> MergeV (IDictionary<object,object>? m)
         {
             Bytecode.AddStep("mergeV", m);
             return Wrap<TStart, Vertex>(this);
@@ -1259,7 +1263,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> MergeV (ITraversal t)
+        public GraphTraversal<TStart, Vertex> MergeV (ITraversal? t)
         {
             Bytecode.AddStep("mergeV", t);
             return Wrap<TStart, Vertex>(this);
@@ -1304,7 +1308,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Option (object pickToken, ITraversal traversalOption)
+        public GraphTraversal<TStart, TEnd> Option (object pickToken, ITraversal? traversalOption)
         {
             Bytecode.AddStep("option", pickToken, traversalOption);
             return Wrap<TStart, TEnd>(this);
@@ -1313,7 +1317,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Option (object pickToken, IDictionary<object,object> traversalOption)
+        public GraphTraversal<TStart, TEnd> Option (object pickToken, IDictionary<object,object>? traversalOption)
         {
             Bytecode.AddStep("option", pickToken, traversalOption);
             return Wrap<TStart, TEnd>(this);
@@ -1322,7 +1326,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Option (ITraversal traversalOption)
+        public GraphTraversal<TStart, TEnd> Option (ITraversal? traversalOption)
         {
             Bytecode.AddStep("option", traversalOption);
             return Wrap<TStart, TEnd>(this);
@@ -1380,11 +1384,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the out step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> Out (params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> Out (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("out", args.ToArray());
             return Wrap<TStart, Vertex>(this);
@@ -1393,11 +1397,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the outE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> OutE (params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> OutE (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("outE", args.ToArray());
             return Wrap<TStart, Edge>(this);
@@ -1478,14 +1482,15 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the project step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Project<TNewEnd> (string projectKey, params string[] otherProjectKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Project<TNewEnd>(string? projectKey,
+            params string?[] otherProjectKeys)
         {
             // Using null as a key is allowed in Java, but we cannot support it in .NET as null is not allowed as a
             //  Dictionary key.
             if (projectKey == null) throw new ArgumentNullException(nameof(projectKey));
             if (otherProjectKeys == null) throw new ArgumentNullException(nameof(otherProjectKeys));
             
-            var args = new List<object>(1 + otherProjectKeys.Length) { projectKey };
+            var args = new List<object?>(1 + otherProjectKeys.Length) { projectKey };
             args.AddRange(otherProjectKeys);
             Bytecode.AddStep("project", args.ToArray());
             return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
@@ -1494,13 +1499,13 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the properties step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Properties<TNewEnd> (params string[] propertyKeys)
+        public GraphTraversal<TStart, TNewEnd> Properties<TNewEnd> (params string?[] propertyKeys)
         {
             // Using null as a key is allowed in Java, but we cannot support it in .NET as null is not allowed as a
             //  Dictionary key.
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("properties", args.ToArray());
             return Wrap<TStart, TNewEnd>(this);
@@ -1509,12 +1514,12 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the property step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Property(Cardinality cardinality, object key, object value,
-            params object[] keyValues)
+        public GraphTraversal<TStart, TEnd> Property(Cardinality cardinality, object? key, object? value,
+            params object?[] keyValues)
         {
             if (keyValues == null) throw new ArgumentNullException(nameof(keyValues));
 
-            var args = new List<object>(3 + keyValues.Length) { cardinality, key, value };
+            var args = new List<object?>(3 + keyValues.Length) { cardinality, key, value };
             args.AddRange(keyValues);
             Bytecode.AddStep("property", args.ToArray());
             return Wrap<TStart, TEnd>(this);
@@ -1523,11 +1528,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the property step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> Property (object key, object value, params object[] keyValues)
+        public GraphTraversal<TStart, TEnd> Property (object? key, object? value, params object?[] keyValues)
         {
             if (keyValues == null) throw new ArgumentNullException(nameof(keyValues));
 
-            var args = new List<object>(2 + keyValues.Length) { key, value };
+            var args = new List<object?>(2 + keyValues.Length) { key, value };
             args.AddRange(keyValues);
             Bytecode.AddStep("property", args.ToArray());
             return Wrap<TStart, TEnd>(this);
@@ -1536,11 +1541,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the propertyMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> PropertyMap<TNewEnd> (params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> PropertyMap<TNewEnd> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("propertyMap", args.ToArray());
             return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
@@ -1639,7 +1644,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (Pop pop, string selectKey)
+        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (Pop pop, string? selectKey)
         {
             Bytecode.AddStep("select", pop, selectKey);
             return Wrap<TStart, TNewEnd>(this);
@@ -1648,12 +1653,12 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Select<TNewEnd>(Pop pop, string selectKey1, string selectKey2,
-            params string[] otherSelectKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Select<TNewEnd>(Pop pop, string? selectKey1,
+            string? selectKey2, params string?[] otherSelectKeys)
         {
             if (otherSelectKeys == null) throw new ArgumentNullException(nameof(otherSelectKeys));
 
-            var args = new List<object>(3 + otherSelectKeys.Length) { pop, selectKey1, selectKey2 };
+            var args = new List<object?>(3 + otherSelectKeys.Length) { pop, selectKey1, selectKey2 };
             args.AddRange(otherSelectKeys);
             Bytecode.AddStep("select", args.ToArray());
             return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
@@ -1671,7 +1676,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (string selectKey)
+        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (string? selectKey)
         {
             Bytecode.AddStep("select", selectKey);
             return Wrap<TStart, TNewEnd>(this);
@@ -1680,12 +1685,12 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Select<TNewEnd>(string selectKey1, string selectKey2,
-            params string[] otherSelectKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Select<TNewEnd>(string? selectKey1,
+            string? selectKey2, params string?[] otherSelectKeys)
         {
             if (otherSelectKeys == null) throw new ArgumentNullException(nameof(otherSelectKeys));
 
-            var args = new List<object>(2 + otherSelectKeys.Length) { selectKey1, selectKey2 };
+            var args = new List<object?>(2 + otherSelectKeys.Length) { selectKey1, selectKey2 };
             args.AddRange(otherSelectKeys);
             Bytecode.AddStep("select", args.ToArray());
             return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
@@ -1712,7 +1717,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the sideEffect step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> SideEffect (IConsumer consumer)
+        public GraphTraversal<TStart, TEnd> SideEffect (IConsumer? consumer)
         {
             Bytecode.AddStep("sideEffect", consumer);
             return Wrap<TStart, TEnd>(this);
@@ -1847,11 +1852,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the to step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> To (Direction direction, params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> To (Direction? direction, params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
 
-            var args = new List<object>(1 + edgeLabels.Length) { direction };
+            var args = new List<object?>(1 + edgeLabels.Length) { direction };
             args.AddRange(edgeLabels);
             Bytecode.AddStep("to", args.ToArray());
             return Wrap<TStart, Vertex>(this);
@@ -1860,7 +1865,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the to step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> To (string toStepLabel)
+        public GraphTraversal<TStart, TEnd> To (string? toStepLabel)
         {
             Bytecode.AddStep("to", toStepLabel);
             return Wrap<TStart, TEnd>(this);
@@ -1887,11 +1892,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the toE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Edge> ToE (Direction direction, params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> ToE (Direction? direction, params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(1 + edgeLabels.Length) {direction};
+            var args = new List<object?>(1 + edgeLabels.Length) {direction};
             args.AddRange(edgeLabels);
             Bytecode.AddStep("toE", args.ToArray());
             return Wrap<TStart, Edge>(this);
@@ -1900,7 +1905,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the toV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, Vertex> ToV (Direction direction)
+        public GraphTraversal<TStart, Vertex> ToV (Direction? direction)
         {
             Bytecode.AddStep("toV", direction);
             return Wrap<TStart, Vertex>(this);
@@ -1976,11 +1981,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the valueMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, IDictionary<TKey, TValue>> ValueMap<TKey, TValue> (params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<TKey, TValue>> ValueMap<TKey, TValue> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("valueMap", args.ToArray());
             return Wrap<TStart, IDictionary<TKey, TValue>>(this);
@@ -1990,11 +1995,11 @@ namespace Gremlin.Net.Process.Traversal
         ///     Adds the valueMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
         public GraphTraversal<TStart, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens,
-            params string[] propertyKeys)
+            params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
 
-            var args = new List<object>(1 + propertyKeys.Length) { includeTokens };
+            var args = new List<object?>(1 + propertyKeys.Length) { includeTokens };
             args.AddRange(propertyKeys);
             Bytecode.AddStep("valueMap", args.ToArray());
             return Wrap<TStart, IDictionary<TKey, TValue>>(this);
@@ -2003,11 +2008,11 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the values step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TNewEnd> Values<TNewEnd> (params string[] propertyKeys)
+        public GraphTraversal<TStart, TNewEnd> Values<TNewEnd> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("values", args.ToArray());
             return Wrap<TStart, TNewEnd>(this);
@@ -2052,7 +2057,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the with step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<TStart, TEnd> With (string key, object value)
+        public GraphTraversal<TStart, TEnd> With (string key, object? value)
         {
             Bytecode.AddStep("with", key, value);
             return Wrap<TStart, TEnd>(this);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index 1f3d4dc6e3..218fb7b798 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -38,7 +38,7 @@ namespace Gremlin.Net.Process.Traversal
     /// </summary>
     public class GraphTraversalSource
     {
-        private readonly IRemoteConnection _connection;
+        private readonly IRemoteConnection? _connection;
 
         public bool IsSessionBound => _connection is { IsSessionBound: true };
         
@@ -89,7 +89,7 @@ namespace Gremlin.Net.Process.Traversal
             return With(key, true);
         }
 
-        public GraphTraversalSource With(string key, object value)
+        public GraphTraversalSource With(string key, object? value)
         {
             var optionsStrategyInst = Bytecode.SourceInstructions.Find(
                 inst => inst.OperatorName == "withStrategies" && inst.Arguments[0] is OptionsStrategy);
@@ -102,7 +102,7 @@ namespace Gremlin.Net.Process.Traversal
                 return WithStrategies(optionsStrategy);
             }
 
-            optionsStrategy = optionsStrategyInst.Arguments[0];
+            optionsStrategy = optionsStrategyInst.Arguments[0]!;
             optionsStrategy.Configuration[key] = value;
             return new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                 new Bytecode(Bytecode));
@@ -125,7 +125,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue)
+        public GraphTraversalSource WithSack(object? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -133,7 +133,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(object? initialValue, IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -141,7 +141,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue, IUnaryOperator splitOperator)
+        public GraphTraversalSource WithSack(object? initialValue, IUnaryOperator? splitOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -149,7 +149,8 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue, IUnaryOperator splitOperator, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(object? initialValue, IUnaryOperator? splitOperator,
+            IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -157,7 +158,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue)
+        public GraphTraversalSource WithSack(ISupplier? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -165,7 +166,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(ISupplier? initialValue, IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -173,7 +174,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue, IUnaryOperator splitOperator)
+        public GraphTraversalSource WithSack(ISupplier? initialValue, IUnaryOperator? splitOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -181,7 +182,8 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue, IUnaryOperator splitOperator, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(ISupplier? initialValue, IUnaryOperator? splitOperator,
+            IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -189,7 +191,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, object initialValue)
+        public GraphTraversalSource WithSideEffect(string? key, object? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -197,7 +199,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, object initialValue, IBinaryOperator reducer)
+        public GraphTraversalSource WithSideEffect(string? key, object? initialValue, IBinaryOperator reducer)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -205,7 +207,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, ISupplier initialValue)
+        public GraphTraversalSource WithSideEffect(string? key, ISupplier? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -213,7 +215,7 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, ISupplier initialValue, IBinaryOperator reducer)
+        public GraphTraversalSource WithSideEffect(string? key, ISupplier? initialValue, IBinaryOperator? reducer)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -233,20 +235,20 @@ namespace Gremlin.Net.Process.Traversal
             return source;
         }
 
-        public GraphTraversalSource WithoutStrategies(params Type[] traversalStrategyClasses)
+        public GraphTraversalSource WithoutStrategies(params Type?[] traversalStrategyClasses)
         {
             if (traversalStrategyClasses == null) throw new ArgumentNullException(nameof(traversalStrategyClasses));
             
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
-            var args = new List<object>(traversalStrategyClasses.Length);
+            var args = new List<object?>(traversalStrategyClasses.Length);
             args.AddRange(traversalStrategyClasses);
             source.Bytecode.AddSource("withoutStrategies", args.ToArray());
             return source;
         }
 
         [Obsolete("Use the Bindings class instead.", false)]
-        public GraphTraversalSource WithBindings(object bindings)
+        public GraphTraversalSource WithBindings(object? bindings)
         {
             return this;
         }
@@ -277,35 +279,35 @@ namespace Gremlin.Net.Process.Traversal
                 throw new InvalidOperationException(
                     "This GraphTraversalSource is already bound to a transaction - child transactions are not supported");
             }
-            return _connection.Tx(this);
+            return _connection!.Tx(this);
         }
 
         /// <summary>
         ///     Add a GraphComputer class used to execute the traversal.
         ///     This adds a <see cref="VertexProgramStrategy" /> to the strategies.
         /// </summary>
-        public GraphTraversalSource WithComputer(string graphComputer = null, int? workers = null, string persist = null,
-            string result = null, ITraversal vertices = null, ITraversal edges = null,
-            Dictionary<string, dynamic> configuration = null)
+        public GraphTraversalSource WithComputer(string? graphComputer = null, int? workers = null,
+            string? persist = null, string? result = null, ITraversal? vertices = null, ITraversal? edges = null,
+            Dictionary<string, dynamic>? configuration = null)
         {
-            return WithStrategies(new VertexProgramStrategy(graphComputer, workers, persist, result, vertices, edges, configuration));
+            return WithStrategies(new VertexProgramStrategy(graphComputer, workers, persist, result, vertices, edges,
+                configuration));
         }
 
-
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the E step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Edge, Edge> E(params object[] edgesIds)
+        public GraphTraversal<Edge, Edge> E(params object?[]? edgesIds)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
             if (edgesIds == null)
             {
-                traversal.Bytecode.AddStep("E", new object[] { null });
+                traversal.Bytecode.AddStep("E", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(edgesIds.Length);
+                var args = new List<object?>(edgesIds.Length);
                 args.AddRange(edgesIds);
                 traversal.Bytecode.AddStep("E", args.ToArray());
             }
@@ -316,16 +318,16 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the V step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Vertex, Vertex> V(params object[] vertexIds)
+        public GraphTraversal<Vertex, Vertex> V(params object?[]? vertexIds)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
             if (vertexIds == null)
             {
-                traversal.Bytecode.AddStep("V", new object[] { null });
+                traversal.Bytecode.AddStep("V", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(vertexIds.Length);
+                var args = new List<object?>(vertexIds.Length);
                 args.AddRange(vertexIds);
                 traversal.Bytecode.AddStep("V", args.ToArray());
             }
@@ -358,7 +360,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeE step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Edge, Edge> MergeE(IDictionary<object,object> m)
+        public GraphTraversal<Edge, Edge> MergeE(IDictionary<object,object>? m)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeE", m);
@@ -369,7 +371,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeE step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Edge, Edge> MergeE(ITraversal t)
+        public GraphTraversal<Edge, Edge> MergeE(ITraversal? t)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeE", t);
@@ -413,7 +415,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeV step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Vertex, Vertex> MergeV(IDictionary<object,object> m)
+        public GraphTraversal<Vertex, Vertex> MergeV(IDictionary<object,object>? m)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeV", m);
@@ -424,7 +426,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeV step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Vertex, Vertex> MergeV(ITraversal t)
+        public GraphTraversal<Vertex, Vertex> MergeV(ITraversal? t)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeV", t);
@@ -435,19 +437,19 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the inject step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<TStart, TStart> Inject<TStart>(params TStart[] starts)
+        public GraphTraversal<TStart, TStart> Inject<TStart>(params TStart?[]? starts)
         {
             var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
 
             // null starts is treated as g.inject(null) meaning inject a single null traverser
             if (starts == null)
             {
-                traversal.Bytecode.AddStep("inject", new object[] { null });
+                traversal.Bytecode.AddStep("inject", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(starts.Length);
-                args.AddRange(starts.Cast<object>());
+                var args = new List<object?>(starts.Length);
+                args.AddRange(starts.Cast<object?>());
                 traversal.Bytecode.AddStep("inject", args.ToArray());
             }
 
@@ -480,7 +482,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<TStart, TStart> Call<TStart>(string service)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service)
         {
             var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service);
@@ -491,7 +493,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<TStart, TStart> Call<TStart>(string service, IDictionary<object, object> m)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service, IDictionary<object, object>? m)
         {
             var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service, m);
@@ -502,7 +504,7 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<TStart, TStart> Call<TStart>(string service, ITraversal t)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service, ITraversal? t)
         {
             var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service, t);
@@ -513,7 +515,8 @@ namespace Gremlin.Net.Process.Traversal
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<TStart, TStart> Call<TStart>(string service, IDictionary<object, object> m, ITraversal t)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service, IDictionary<object, object>? m,
+            ITraversal? t)
         {
             var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service, m, t);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
index e56b7a2296..17874b502e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
@@ -48,7 +48,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal.
         /// </summary>
-        IEnumerable<Traverser> Traversers { get; set; }
+        IEnumerable<Traverser>? Traversers { get; set; }
 
         /// <summary>
         ///     Iterates all <see cref="Traverser" /> instances in the traversal.
@@ -60,13 +60,13 @@ namespace Gremlin.Net.Process.Traversal
     /// <summary>
     ///     A traversal represents a directed walk over a graph.
     /// </summary>
-    public interface ITraversal<TStart, TEnd> : ITraversal, IEnumerator<TEnd>
+    public interface ITraversal<TStart, TEnd> : ITraversal, IEnumerator<TEnd?>
     {
         /// <summary>
         ///     Gets the next result from the traversal.
         /// </summary>
         /// <returns>The result.</returns>
-        TEnd Next();
+        TEnd? Next();
 
         /// <summary>
         ///     Determines if the traversal contains any additional results for iteration.
@@ -79,7 +79,7 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         /// <param name="amount">The number of results to get.</param>
         /// <returns>The n-results.</returns>
-        IEnumerable<TEnd> Next(int amount);
+        IEnumerable<TEnd?> Next(int amount);
 
         /// <summary>
         ///     Iterates all <see cref="Traverser" /> instances in the traversal.
@@ -97,13 +97,13 @@ namespace Gremlin.Net.Process.Traversal
         ///     Puts all the results into a <see cref="IList{T}" />.
         /// </summary>
         /// <returns>The results in a list.</returns>
-        IList<TEnd> ToList();
+        IList<TEnd?> ToList();
 
         /// <summary>
         ///     Puts all the results into a <see cref="ISet{T}" />.
         /// </summary>
         /// <returns>The results in a set.</returns>
-        ISet<TEnd> ToSet();
+        ISet<TEnd?> ToSet();
 
         /// <summary>
         ///     Starts a promise to execute a function on the current traversal that will be completed in the future.
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
index f6453fe7a5..cf9cd0c9c3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
@@ -36,10 +36,10 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         /// <param name="operatorName">The name of the operator.</param>
         /// <param name="arguments">The arguments.</param>
-        public Instruction(string operatorName, params dynamic[] arguments)
+        public Instruction(string operatorName, params dynamic?[] arguments)
         {
-            OperatorName = operatorName;
-            Arguments = arguments;
+            OperatorName = operatorName ?? throw new ArgumentNullException(nameof(operatorName));
+            Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments));
         }
 
         /// <summary>
@@ -50,7 +50,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets the arguments.
         /// </summary>
-        public dynamic[] Arguments { get; }
+        public dynamic?[] Arguments { get; }
 
         /// <summary>
         ///     String representation of the <see cref="Instruction"/>.
@@ -61,7 +61,7 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <inheritdoc />
-        public bool Equals(Instruction other)
+        public bool Equals(Instruction? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -69,7 +69,7 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -83,15 +83,10 @@ namespace Gremlin.Net.Process.Traversal
             unchecked
             {
                 var hash = 19;
-                if (OperatorName != null)
-                {
-                    hash = hash * 397 + OperatorName.GetHashCode();
-                }
+                hash = hash * 397 + OperatorName.GetHashCode();
 
-                if (Arguments != null)
-                {
-                    hash = Arguments.Aggregate(hash, (current, value) => current * 31 + value.GetHashCode());
-                }
+                hash = Arguments.Aggregate(hash,
+                    (current, value) => current * 31 + (value == null ? 0 : value.GetHashCode()));
 
                 return hash;
             }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
deleted file mode 100644
index a650dc5f57..0000000000
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-#region License
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#endregion
-
-using System.Collections.Generic;
-
-namespace Gremlin.Net.Process.Traversal
-{
-    internal static class NamingConversions
-    {
-        /// <summary>
-        ///     Gets the Java name equivalent for a given enum value
-        /// </summary>
-        internal static string GetEnumJavaName(string typeName, string value)
-        {
-            var key = $"{typeName}.{value}";
-            string javaName;
-            if (!CSharpToJavaEnums.TryGetValue(key, out javaName))
-            {
-                throw new KeyNotFoundException($"Java name for {key} not found");
-            }
-            return javaName;
-        }
-
-        internal static readonly IDictionary<string, string> CSharpToJavaEnums = new Dictionary<string, string>
-        {
-            {"Barrier.NormSack", "normSack"},
-            {"Cardinality.List", "list"},
-            {"Cardinality.Set", "set"},
-            {"Cardinality.Single", "single"},
-            {"Column.Keys", "keys"},
-            {"Column.Values", "values"},
-            {"Direction.Both", "BOTH"},
-            {"Direction.In", "IN"},
-            {"Direction.Out", "OUT"},
-            {"GraphSONVersion.V1_0", "V1_0"},
-            {"GraphSONVersion.V2_0", "V2_0"},
-            {"GraphSONVersion.V3_0", "V3_0"},
-            {"GryoVersion.V1_0", "V1_0"},
-            {"GryoVersion.V3_0", "V3_0"},
-            {"Operator.AddAll", "addAll"},
-            {"Operator.And", "and"},
-            {"Operator.Assign", "assign"},
-            {"Operator.Div", "div"},
-            {"Operator.Max", "max"},
-            {"Operator.Min", "min"},
-            {"Operator.Minus", "minus"},
-            {"Operator.Mult", "mult"},
-            {"Operator.Or", "or"},
-            {"Operator.Sum", "sum"},
-            {"Operator.SumLong", "sumLong"},
-            {"Order.Decr", "decr"},
-            {"Order.Incr", "incr"},
-            {"Order.Shuffle", "shuffle"},
-            {"Order.Asc", "asc"},
-            {"Order.Desc", "desc"},
-            {"Pick.Any", "any"},
-            {"Pick.None", "none"},
-            {"Pop.All", "all"},
-            {"Pop.First", "first"},
-            {"Pop.Last", "last"},
-            {"Pop.Mixed", "mixed"},
-            {"Scope.Global", "global"},
-            {"Scope.Local", "local"},
-            {"T.Id", "id"},
-            {"T.Key", "key"},
-            {"T.Label", "label"},
-            {"T.Value", "value"}
-
-        };
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
index 733352b795..2e4e2b3f7f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
@@ -41,7 +41,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <param name="operatorName">The name of the predicate.</param>
         /// <param name="value">The value of the predicate.</param>
         /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
-        public P(string operatorName, dynamic value, P other = null)
+        public P(string operatorName, dynamic? value, P? other = null)
         {
             OperatorName = operatorName;
             Value = value;
@@ -56,12 +56,12 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets the value of the predicate.
         /// </summary>
-        public dynamic Value { get; }
+        public dynamic? Value { get; }
 
         /// <summary>
         ///     Gets an optional other predicate that is used as an argument for this predicate.
         /// </summary>
-        public P Other { get; }
+        public P? Other { get; }
 
         /// <summary>
         ///     Returns a composed predicate that represents a logical AND of this predicate and another.
@@ -83,86 +83,86 @@ namespace Gremlin.Net.Process.Traversal
             return new P("or", this, otherPredicate);
         }
 
-        public static P Between(params object[] args)
+        public static P Between(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("between", value);
         }
 
-        public static P Eq(params object[] args)
+        public static P Eq(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("eq", value);
         }
 
-        public static P Gt(params object[] args)
+        public static P Gt(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("gt", value);
         }
 
-        public static P Gte(params object[] args)
+        public static P Gte(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("gte", value);
         }
 
-        public static P Inside(params object[] args)
+        public static P Inside(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("inside", value);
         }
 
-        public static P Lt(params object[] args)
+        public static P Lt(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("lt", value);
         }
 
-        public static P Lte(params object[] args)
+        public static P Lte(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("lte", value);
         }
 
-        public static P Neq(params object[] args)
+        public static P Neq(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("neq", value);
         }
 
-        public static P Not(params object[] args)
+        public static P Not(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("not", value);
         }
 
-        public static P Outside(params object[] args)
+        public static P Outside(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("outside", value);
         }
 
-        public static P Test(params object[] args)
+        public static P Test(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("test", value);
         }
 
-        public static P Within(params object[] args)
+        public static P Within(params object[]? args)
         {
-            var x = args != null && args.Length == 1 && args[0] is ICollection collection ? collection : args;
+            var x = args is { Length: 1 } && args[0] is ICollection collection ? collection : args;
             return new P("within", ToGenericList(x));
         }
 
-        public static P Without(params object[] args)
+        public static P Without(params object[]? args)
         {
-            var x = args != null && args.Length == 1 && args[0] is ICollection collection ? collection : args;
+            var x = args is { Length: 1 } && args[0] is ICollection collection ? collection : args;
             return new P("without", ToGenericList(x));
         }
 
 
-        private static List<object> ToGenericList(IEnumerable collection)
+        private static List<object> ToGenericList(IEnumerable? collection)
         {
             return collection?.Cast<object>().ToList() ?? Enumerable.Empty<object>().ToList();
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs
index 11b8528665..1c7376d8bf 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs
@@ -84,10 +84,10 @@ namespace Gremlin.Net.Process.Traversal.Strategy
         /// <summary>
         ///     Gets the configuration of the strategy.
         /// </summary>
-        public Dictionary<string, dynamic> Configuration { get; } = new Dictionary<string, dynamic>();
+        public Dictionary<string, dynamic?> Configuration { get; } = new();
 
         /// <inheritdoc />
-        public bool Equals(AbstractTraversalStrategy other)
+        public bool Equals(AbstractTraversalStrategy? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -106,7 +106,7 @@ namespace Gremlin.Net.Process.Traversal.Strategy
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs
index 6ae8876543..ffa38fcd9e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs
@@ -32,7 +32,7 @@ namespace Gremlin.Net.Process.Traversal.Strategy.Decoration
         {
         }
 
-        public HaltedTraverserStrategy(string haltedTraverserFactoryName = null)
+        public HaltedTraverserStrategy(string? haltedTraverserFactoryName = null)
             : this()
         {
             if (haltedTraverserFactoryName != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs
index 8c59ad4bee..34f7b55096 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs
@@ -49,8 +49,8 @@ namespace Gremlin.Net.Process.Traversal.Strategy.Decoration
         /// </param>
         /// <param name="readPartitions">Specifies the partition of the graph to read from.</param>
         /// <param name="includeMetaProperties">Set to true if vertex properties should get assigned to partitions.</param>
-        public PartitionStrategy(string partitionKey = null, string writePartition = null,
-            IEnumerable<string> readPartitions = null, bool? includeMetaProperties = null)
+        public PartitionStrategy(string? partitionKey = null, string? writePartition = null,
+            IEnumerable<string>? readPartitions = null, bool? includeMetaProperties = null)
             : this()
         {
             if (partitionKey != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs
index af312d656c..141b851203 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs
@@ -44,8 +44,8 @@ namespace Gremlin.Net.Process.Traversal.Strategy.Decoration
         /// <param name="edges">Constrains edges for the <see cref="ITraversal" />.</param>
         /// <param name="vertexProperties">Constrains vertex properties for the <see cref="ITraversal" />.</param>
         /// <param name="checkAdjacentVertices">Determines if filters are applied to the adjacent vertices of an edge.</param>
-        public SubgraphStrategy(ITraversal vertices = null, ITraversal edges = null,
-            ITraversal vertexProperties = null, bool? checkAdjacentVertices = null)
+        public SubgraphStrategy(ITraversal? vertices = null, ITraversal? edges = null,
+            ITraversal? vertexProperties = null, bool? checkAdjacentVertices = null)
             : this()
         {
             if (vertices != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs
index 17bfbaa426..149dfe7537 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs
@@ -35,9 +35,9 @@ namespace Gremlin.Net.Process.Traversal.Strategy.Decoration
         {
         }
 
-        public VertexProgramStrategy(string graphComputer = null, int? workers = null, string persist = null,
-            string result = null, ITraversal vertices = null, ITraversal edges = null,
-            Dictionary<string, dynamic> configuration = null)
+        public VertexProgramStrategy(string? graphComputer = null, int? workers = null, string? persist = null,
+            string? result = null, ITraversal? vertices = null, ITraversal? edges = null,
+            Dictionary<string, dynamic>? configuration = null)
             : this()
         {
             if (graphComputer != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs
index 1586580844..e989f48d32 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs
@@ -43,7 +43,7 @@ namespace Gremlin.Net.Process.Traversal.Strategy.Optimization
         ///     Initializes a new instance of the <see cref="ProductiveByStrategy" /> class.
         /// </summary>
         /// <param name="productiveKeys">Specifies keys that will always be productive.</param>
-        public ProductiveByStrategy(IEnumerable<object> productiveKeys = null)
+        public ProductiveByStrategy(IEnumerable<object>? productiveKeys = null)
             : this()
         {
             if (productiveKeys != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
index eccae0d3bd..204f9d8d7b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
@@ -47,7 +47,7 @@ namespace Gremlin.Net.Process.Traversal.Strategy.Verification
         /// <param name="throwException">Throw an exception if a reserved key is used.</param>
         /// <param name="keys">List of keys to define as reserved. If not set then the defaults are used.</param>
         public ReservedKeysVerificationStrategy(bool logWarning = false, bool throwException = false,
-            List<string> keys = null)
+            List<string>? keys = null)
             : this()
         {
             Configuration["logWarning"] = logWarning;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
index 2bf49684b5..9a97d1a044 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
@@ -41,7 +41,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <param name="operatorName">The name of the predicate.</param>
         /// <param name="value">The value of the predicate.</param>
         /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
-        public TextP(string operatorName, string value, P other = null) : base(operatorName, value, other)
+        public TextP(string operatorName, string value, P? other = null) : base(operatorName, value, other)
         {
         }
 
@@ -86,11 +86,6 @@ namespace Gremlin.Net.Process.Traversal
             return new TextP("notRegex", value);
         }
 
-        private static T[] ToGenericArray<T>(ICollection<T> collection)
-        {
-            return collection?.ToArray() ?? new T[0];
-        }
-
         /// <inheritdoc />
         public override string ToString()
         {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs
index 867c719a8d..98dc5c49e6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs
@@ -107,7 +107,7 @@ namespace Gremlin.Net.Process.Traversal.Translator
             return $".{step.OperatorName}({TranslateArguments(step.Arguments)})";
         }
         
-        private string TranslateWithArguments(dynamic[] arguments)
+        private string TranslateWithArguments(dynamic?[] arguments)
         {
             if (arguments[0] == WithOptions.Tokens)
             {
@@ -138,10 +138,10 @@ namespace Gremlin.Net.Process.Traversal.Translator
             { WithOptions.Map, "WithOptions.map" }
         };
 
-        private string TranslateArguments(IEnumerable<object> arguments) =>
+        private string TranslateArguments(IEnumerable<object?> arguments) =>
             string.Join(", ", arguments.Select(TranslateArgument));
 
-        private string TranslateArgument(object argument)
+        private string TranslateArgument(object? argument)
         {
             return argument switch
             {
@@ -157,7 +157,7 @@ namespace Gremlin.Net.Process.Traversal.Translator
                 IEnumerable e => TranslateCollection(e),
                 ITraversal t => TranslateTraversal(t),
                 AbstractTraversalStrategy strategy => TranslateStrategy(strategy),
-                _ => Convert.ToString(argument, CultureInfo.InvariantCulture)
+                _ => Convert.ToString(argument, CultureInfo.InvariantCulture)!
             };
         }
         
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs
index 573e57f4b4..e00644ebdb 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs
@@ -33,7 +33,7 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         /// <param name="obj">The object of the traverser.</param>
         /// <param name="bulk">The number of traversers represented in this traverser.</param>
-        public Traverser(dynamic obj, long bulk = 1)
+        public Traverser(dynamic? obj, long bulk = 1)
         {
             Object = obj;
             Bulk = bulk;
@@ -42,7 +42,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Gets the object of this traverser.
         /// </summary>
-        public dynamic Object { get; }
+        public dynamic? Object { get; }
 
         /// <summary>
         ///     Gets the number of traversers represented in this traverser.
@@ -58,7 +58,7 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index bc62fc3695..17adcda88c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -42,7 +42,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the V step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> V(params object[] vertexIdsOrElements)
+        public static GraphTraversal<object, Vertex> V(params object?[]? vertexIdsOrElements)
         {
             return vertexIdsOrElements is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().V()
@@ -52,7 +52,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the E step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> E(params object[] edgeIdsOrElements)
+        public static GraphTraversal<object, Edge> E(params object?[]? edgeIdsOrElements)
         {
             return edgeIdsOrElements is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().E()
@@ -162,7 +162,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the both step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> Both(params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> Both(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().Both()
@@ -172,7 +172,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the bothE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> BothE(params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> BothE(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().BothE()
@@ -190,7 +190,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the branch step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Branch<E2>(IFunction function)
+        public static GraphTraversal<object, E2> Branch<E2>(IFunction? function)
         {
             return new GraphTraversal<object, E2>().Branch<E2>(function);            
         }
@@ -206,7 +206,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service)
+        public static GraphTraversal<object, E2> Call<E2>(string? service)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service);
         }
@@ -214,7 +214,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service, IDictionary<object,object> m)
+        public static GraphTraversal<object, E2> Call<E2>(string? service, IDictionary<object,object>? m)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service, m);
         }
@@ -222,7 +222,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service, ITraversal t)
+        public static GraphTraversal<object, E2> Call<E2>(string? service, ITraversal? t)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service, t);
         }
@@ -230,7 +230,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service, IDictionary<object,object> m, ITraversal t)
+        public static GraphTraversal<object, E2> Call<E2>(string? service, IDictionary<object,object>? m, ITraversal? t)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service, m, t);
         }
@@ -316,7 +316,7 @@ namespace Gremlin.Net.Process.Traversal
         /// </summary>
         public static GraphTraversal<object, E2> Constant<E2>(E2 a)
         {
-            return new GraphTraversal<object, E2>().Constant<E2>(a);            
+            return new GraphTraversal<object, E2>().Constant(a);            
         }
 
         /// <summary>
@@ -346,7 +346,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the dedup step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Dedup(Scope scope, params string[] dedupLabels)
+        public static GraphTraversal<object, object> Dedup(Scope scope, params string?[] dedupLabels)
         {
             return dedupLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().Dedup(scope)
@@ -356,7 +356,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the dedup step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Dedup(params string[] dedupLabels)
+        public static GraphTraversal<object, object> Dedup(params string?[] dedupLabels)
         {
             return dedupLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().Dedup()
@@ -382,7 +382,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the elementMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<object, E2>> ElementMap<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<object, E2>> ElementMap<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<object, E2>>().ElementMap<E2>()
@@ -424,7 +424,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the fail step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Fail(string msg)
+        public static GraphTraversal<object, object> Fail(string? msg)
         {
             return new GraphTraversal<object, object>().Fail(msg);
         }
@@ -432,7 +432,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the filter step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Filter(IPredicate predicate)
+        public static GraphTraversal<object, object> Filter(IPredicate? predicate)
         {
             return new GraphTraversal<object, object>().Filter(predicate);            
         }
@@ -448,7 +448,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the flatMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> FlatMap<E2>(IFunction function)
+        public static GraphTraversal<object, E2> FlatMap<E2>(IFunction? function)
         {
             return new GraphTraversal<object, E2>().FlatMap<E2>(function);            
         }
@@ -472,9 +472,9 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the fold step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Fold<E2>(E2 seed, IBiFunction foldFunction)
+        public static GraphTraversal<object, E2> Fold<E2>(E2 seed, IBiFunction? foldFunction)
         {
-            return new GraphTraversal<object, E2>().Fold<E2>(seed, foldFunction);            
+            return new GraphTraversal<object, E2>().Fold(seed, foldFunction);            
         }
 
         /// <summary>
@@ -512,7 +512,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey)
+        public static GraphTraversal<object, object> Has(string? propertyKey)
         {
             return new GraphTraversal<object, object>().Has(propertyKey);            
         }
@@ -520,7 +520,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey, object value)
+        public static GraphTraversal<object, object> Has(string? propertyKey, object? value)
         {
             return new GraphTraversal<object, object>().Has(propertyKey, value);            
         }
@@ -528,7 +528,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey, P predicate)
+        public static GraphTraversal<object, object> Has(string? propertyKey, P? predicate)
         {
             return new GraphTraversal<object, object>().Has(propertyKey, predicate);            
         }
@@ -536,7 +536,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string label, string propertyKey, object value)
+        public static GraphTraversal<object, object> Has(string? label, string? propertyKey, object? value)
         {
             return new GraphTraversal<object, object>().Has(label, propertyKey, value);            
         }
@@ -544,7 +544,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string label, string propertyKey, P predicate)
+        public static GraphTraversal<object, object> Has(string? label, string? propertyKey, P? predicate)
         {
             return new GraphTraversal<object, object>().Has(label, propertyKey, predicate);            
         }
@@ -552,7 +552,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey, ITraversal propertyTraversal)
+        public static GraphTraversal<object, object> Has(string? propertyKey, ITraversal propertyTraversal)
         {
             return new GraphTraversal<object, object>().Has(propertyKey, propertyTraversal);            
         }
@@ -560,7 +560,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(T accessor, object value)
+        public static GraphTraversal<object, object> Has(T accessor, object? value)
         {
             return new GraphTraversal<object, object>().Has(accessor, value);            
         }
@@ -568,7 +568,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(T accessor, P predicate)
+        public static GraphTraversal<object, object> Has(T accessor, P? predicate)
         {
             return new GraphTraversal<object, object>().Has(accessor, predicate);            
         }
@@ -584,7 +584,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasId step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasId(object id, params object[] otherIds)
+        public static GraphTraversal<object, object> HasId(object? id, params object?[]? otherIds)
         {
             return otherIds is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasId(id)
@@ -594,7 +594,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasId step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasId(P predicate)
+        public static GraphTraversal<object, object> HasId(P? predicate)
         {
             return new GraphTraversal<object, object>().HasId(predicate);            
         }
@@ -602,7 +602,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasKey step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasKey(P predicate)
+        public static GraphTraversal<object, object> HasKey(P? predicate)
         {
             return new GraphTraversal<object, object>().HasKey(predicate);            
         }
@@ -610,7 +610,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasKey step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasKey(string label, params string[] otherLabels)
+        public static GraphTraversal<object, object> HasKey(string? label, params string?[]? otherLabels)
         {
             return otherLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasKey(label)
@@ -620,7 +620,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasLabel step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasLabel(P predicate)
+        public static GraphTraversal<object, object> HasLabel(P? predicate)
         {
             return new GraphTraversal<object, object>().HasLabel(predicate);            
         }
@@ -628,7 +628,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasLabel step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasLabel(string label, params string[] otherLabels)
+        public static GraphTraversal<object, object> HasLabel(string? label, params string?[]? otherLabels)
         {
             return otherLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasLabel(label)
@@ -638,7 +638,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasNot step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasNot(string propertyKey)
+        public static GraphTraversal<object, object> HasNot(string? propertyKey)
         {
             return new GraphTraversal<object, object>().HasNot(propertyKey);            
         }
@@ -646,7 +646,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasValue step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasValue(object value, params object[] values)
+        public static GraphTraversal<object, object> HasValue(object? value, params object?[]? values)
         {
             return values is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasValue(value)
@@ -656,7 +656,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasValue step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasValue(P predicate)
+        public static GraphTraversal<object, object> HasValue(P? predicate)
         {
             return new GraphTraversal<object, object>().HasValue(predicate);            
         }
@@ -680,7 +680,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the in step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> In(params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> In(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().In()
@@ -690,7 +690,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the inE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> InE(params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> InE(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().InE()
@@ -716,7 +716,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the inject step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Inject(params object[] injections)
+        public static GraphTraversal<object, object> Inject(params object?[] injections)
         {
             return injections is { Length: 0 }
                 ? new GraphTraversal<object, object>().Inject()
@@ -726,7 +726,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the is step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Is(object value)
+        public static GraphTraversal<object, object> Is(object? value)
         {
             return new GraphTraversal<object, object>().Is(value);            
         }
@@ -734,7 +734,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the is step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Is(P predicate)
+        public static GraphTraversal<object, object> Is(P? predicate)
         {
             return new GraphTraversal<object, object>().Is(predicate);            
         }
@@ -790,7 +790,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the loops step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, int> Loops(string loopName)
+        public static GraphTraversal<object, int> Loops(string? loopName)
         {
             return new GraphTraversal<object, int>().Loops(loopName);            
         }
@@ -798,7 +798,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the map step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Map<E2>(IFunction function)
+        public static GraphTraversal<object, E2> Map<E2>(IFunction? function)
         {
             return new GraphTraversal<object, E2>().Map<E2>(function);            
         }
@@ -872,7 +872,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> MergeE (IDictionary<object,object> m)
+        public static GraphTraversal<object, Edge> MergeE (IDictionary<object,object>? m)
         {
             return new GraphTraversal<object, Edge>().MergeE(m);
         }
@@ -880,7 +880,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> MergeE (ITraversal t)
+        public static GraphTraversal<object, Edge> MergeE (ITraversal? t)
         {
             return new GraphTraversal<object, Edge>().MergeE(t);
         }
@@ -896,7 +896,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, Vertex> MergeV (IDictionary<object,object> m)
+        public static GraphTraversal<object, Vertex> MergeV (IDictionary<object,object>? m)
         {
             return new GraphTraversal<object, Vertex>().MergeV(m);
         }
@@ -904,7 +904,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, Vertex> MergeV (ITraversal t)
+        public static GraphTraversal<object, Vertex> MergeV (ITraversal? t)
         {
             return new GraphTraversal<object, Vertex>().MergeV(t);
         }
@@ -978,7 +978,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the out step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> Out(params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> Out(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().Out()
@@ -988,7 +988,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the outE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> OutE(params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> OutE(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().OutE()
@@ -1014,7 +1014,8 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the project step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> Project<E2>(string projectKey, params string[] projectKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> Project<E2>(string? projectKey,
+            params string?[] projectKeys)
         {
             return projectKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().Project<E2>(projectKey)
@@ -1024,7 +1025,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the properties step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Properties<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, E2> Properties<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, E2>().Properties<E2>()
@@ -1034,7 +1035,8 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the property step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Property(Cardinality cardinality, object key, object value, params object[] keyValues)
+        public static GraphTraversal<object, object> Property(Cardinality cardinality, object? key, object? value,
+            params object?[] keyValues)
         {
             return keyValues is { Length: 0 }
                 ? new GraphTraversal<object, object>().Property(cardinality, key, value)
@@ -1044,7 +1046,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the property step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Property(object key, object value, params object[] keyValues)
+        public static GraphTraversal<object, object> Property(object? key, object? value, params object?[] keyValues)
         {
             return keyValues is { Length: 0 }
                 ? new GraphTraversal<object, object>().Property(key, value)
@@ -1054,7 +1056,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the propertyMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> PropertyMap<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> PropertyMap<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().PropertyMap<E2>()
@@ -1136,7 +1138,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Select<E2>(Pop pop, string selectKey)
+        public static GraphTraversal<object, E2> Select<E2>(Pop pop, string? selectKey)
         {
             return new GraphTraversal<object, E2>().Select<E2>(pop, selectKey);            
         }
@@ -1144,11 +1146,13 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(Pop pop, string selectKey1, string selectKey2, params string[] otherSelectKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(Pop pop, string? selectKey1,
+            string? selectKey2, params string?[] otherSelectKeys)
         {
             return otherSelectKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(pop, selectKey1, selectKey2)
-                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(pop, selectKey1, selectKey2, otherSelectKeys);            
+                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(pop, selectKey1, selectKey2,
+                    otherSelectKeys);
         }
 
         /// <summary>
@@ -1162,7 +1166,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Select<E2>(string selectKey)
+        public static GraphTraversal<object, E2> Select<E2>(string? selectKey)
         {
             return new GraphTraversal<object, E2>().Select<E2>(selectKey);            
         }
@@ -1170,11 +1174,13 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(string selectKey1, string selectKey2, params string[] otherSelectKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(string? selectKey1, string? selectKey2,
+            params string?[] otherSelectKeys)
         {
             return otherSelectKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(selectKey1, selectKey2)
-                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(selectKey1, selectKey2, otherSelectKeys);            
+                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(selectKey1, selectKey2,
+                    otherSelectKeys);
         }
 
         /// <summary>
@@ -1188,7 +1194,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the sideEffect step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> SideEffect(IConsumer consumer)
+        public static GraphTraversal<object, object> SideEffect(IConsumer? consumer)
         {
             return new GraphTraversal<object, object>().SideEffect(consumer);            
         }
@@ -1308,7 +1314,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the to step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> To(Direction direction, params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> To(Direction? direction, params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().To(direction)
@@ -1318,7 +1324,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the toE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> ToE(Direction direction, params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> ToE(Direction? direction, params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().ToE(direction)
@@ -1328,7 +1334,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the toV step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> ToV(Direction direction)
+        public static GraphTraversal<object, Vertex> ToV(Direction? direction)
         {
             return new GraphTraversal<object, Vertex>().ToV(direction);            
         }
@@ -1394,7 +1400,8 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the valueMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(
+            params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<TKey, TValue>>().ValueMap<TKey, TValue>()
@@ -1404,7 +1411,8 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the valueMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens, params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens,
+            params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<TKey, TValue>>().ValueMap<TKey, TValue>(includeTokens)
@@ -1414,7 +1422,7 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the values step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Values<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, E2> Values<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, E2>().Values<E2>()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
index 27d5de114a..01cace8009 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Process
             }
             catch (AggregateException ex)
             {
-                if (ex.InnerExceptions.Count == 1)
+                if (ex.InnerException != null)
                 {
                     ExceptionDispatchInfo.Capture(ex.InnerException).Throw();   
                 }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs
index fddbd693ae..780ac06240 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Structure
         /// <param name="outV">The outgoing/tail vertex of the edge.</param>
         /// <param name="label">The label of the edge.</param>
         /// <param name="inV">The incoming/head vertex of the edge.</param>
-        public Edge(object id, Vertex outV, string label, Vertex inV)
+        public Edge(object? id, Vertex outV, string label, Vertex inV)
             : base(id, label)
         {
             OutV = outV;
@@ -43,14 +43,14 @@ namespace Gremlin.Net.Structure
         }
 
         /// <summary>
-        ///     Gets or sets the incoming/head vertex of this edge.
+        ///     Gets the incoming/head vertex of this edge.
         /// </summary>
-        public Vertex InV { get; set; }
+        public Vertex InV { get; }
 
         /// <summary>
-        ///     Gets or sets the outgoing/tail vertex of this edge.
+        ///     Gets the outgoing/tail vertex of this edge.
         /// </summary>
-        public Vertex OutV { get; set; }
+        public Vertex OutV { get; }
 
         /// <inheritdoc />
         public override string ToString()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
index f4fc847c0b..a837447792 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Structure
         /// </summary>
         /// <param name="id">The id of the element.</param>
         /// <param name="label">The label of the element.</param>
-        protected Element(object id, string label)
+        protected Element(object? id, string label)
         {
             Id = id;
             Label = label;
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Structure
         /// <summary>
         ///     Gets the id of this <see cref="Element" />.
         /// </summary>
-        public object Id { get; }
+        public object? Id { get; }
 
         /// <summary>
         ///     Gets the label of this <see cref="Element" />.
@@ -52,7 +52,7 @@ namespace Gremlin.Net.Structure
         public string Label { get; }
 
         /// <inheritdoc />
-        public bool Equals(Element other)
+        public bool Equals(Element? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -60,7 +60,7 @@ namespace Gremlin.Net.Structure
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -71,7 +71,7 @@ namespace Gremlin.Net.Structure
         /// <inheritdoc />
         public override int GetHashCode()
         {
-            return Id.GetHashCode();
+            return Id != null ? Id.GetHashCode() : 0;
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
index ee33cee6e1..b5c5e0c2f6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
@@ -108,7 +108,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         }
 
         /// <inheritdoc />
-        public bool Equals(DataType other)
+        public bool Equals(DataType? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -116,7 +116,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs
index 0ea14358e3..eeee25dae0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs
@@ -49,7 +49,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// Initializes a new instance of the <see cref="GraphBinaryMessageSerializer" /> class.
         /// </summary>
         /// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for serialization.</param>
-        public GraphBinaryMessageSerializer(TypeSerializerRegistry registry = null)
+        public GraphBinaryMessageSerializer(TypeSerializerRegistry? registry = null)
         {
             _reader = new GraphBinaryReader(registry);
             _writer = new GraphBinaryWriter(registry);
@@ -81,7 +81,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         }
 
         /// <inheritdoc />
-        public async Task<ResponseMessage<List<object>>> DeserializeMessageAsync(byte[] message,
+        public async Task<ResponseMessage<List<object>>?> DeserializeMessageAsync(byte[] message,
             CancellationToken cancellationToken = default)
         {
             using var stream = new MemoryStream(message);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs
index 297bb41f51..6b11360309 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs
@@ -38,7 +38,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// Initializes a new instance of the <see cref="GraphBinaryReader" /> class.
         /// </summary>
         /// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for deserialization.</param>
-        public GraphBinaryReader(TypeSerializerRegistry registry = null)
+        public GraphBinaryReader(TypeSerializerRegistry? registry = null)
         {
             _registry = registry ?? TypeSerializerRegistry.Instance;
         }
@@ -47,15 +47,29 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// Reads only the value for a specific type <typeparamref name="T"/>.
         /// </summary>
         /// <param name="stream">The GraphBinary data to parse.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <typeparam name="T">The type of the object to read.</typeparam>
         /// <returns>The read value.</returns>
-        public async Task<object> ReadValueAsync<T>(Stream stream, bool nullable,
+        public async Task<object?> ReadNullableValueAsync<T>(Stream stream,
             CancellationToken cancellationToken = default)
         {
             var typedSerializer = _registry.GetSerializerFor(typeof(T));
-            return await typedSerializer.ReadValueAsync(stream, this, nullable, cancellationToken)
+            return await typedSerializer.ReadNullableValueAsync(stream, this, cancellationToken)
+                .ConfigureAwait(false);
+        }
+        
+        /// <summary>
+        /// Reads only the value for a specific type <typeparamref name="T"/>.
+        /// </summary>
+        /// <param name="stream">The GraphBinary data to parse.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <typeparam name="T">The type of the object to read.</typeparam>
+        /// <returns>The read value.</returns>
+        public async Task<object> ReadNonNullableValueAsync<T>(Stream stream,
+            CancellationToken cancellationToken = default)
+        {
+            var typedSerializer = _registry.GetSerializerFor(typeof(T));
+            return await typedSerializer.ReadNonNullableValueAsync(stream, this, cancellationToken)
                 .ConfigureAwait(false);
         }
 
@@ -65,14 +79,14 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// <param name="stream">The GraphBinary data to parse.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The read value.</returns>
-        public async Task<object> ReadAsync(Stream stream, CancellationToken cancellationToken = default)
+        public async Task<object?> ReadAsync(Stream stream, CancellationToken cancellationToken = default)
         {
             var type = DataType.FromTypeCode(await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false));
 
             if (type == DataType.UnspecifiedNull)
             {
                 await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false); // read value byte to advance the index
-                return default; // should be null (TODO?)
+                return null;
             }
 
             ITypeSerializer typeSerializer;
@@ -82,8 +96,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             }
             else
             {
-                var customTypeName =
-                    (string)await ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false);
+                var customTypeName = (string)await ReadNonNullableValueAsync<string>(stream, cancellationToken)
+                    .ConfigureAwait(false);
                 typeSerializer = _registry.GetSerializerForCustomType(customTypeName);
             }
             
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs
index 132707c19e..876611f5ae 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -50,36 +51,46 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// Initializes a new instance of the <see cref="GraphBinaryWriter" /> class.
         /// </summary>
         /// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for serialization.</param>
-        public GraphBinaryWriter(TypeSerializerRegistry registry = null)
+        public GraphBinaryWriter(TypeSerializerRegistry? registry = null)
         {
             _registry = registry ?? TypeSerializerRegistry.Instance;
         }
 
         /// <summary>
-        /// Writes a value without including type information.
+        /// Writes a nullable value without including type information.
         /// </summary>
         /// <param name="value">The value to write.</param>
         /// <param name="stream">The stream to write to.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
-        public async Task WriteValueAsync(object value, Stream stream, bool nullable,
+        public async Task WriteNullableValueAsync(object? value, Stream stream,
             CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
-                if (!nullable)
-                {
-                    throw new IOException("Unexpected null value when nullable is false");
-                }
-
                 await WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
                 return;
             }
             
             var valueType = value.GetType();
             var serializer = _registry.GetSerializerFor(valueType);
-            await serializer.WriteValueAsync(value, stream, this, nullable, cancellationToken).ConfigureAwait(false);
+            await serializer.WriteNullableValueAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
+        }
+        
+        /// <summary>
+        /// Writes a non-nullable value without including type information.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        /// <param name="stream">The stream to write to.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <returns>A task that represents the asynchronous write operation.</returns>
+        public async Task WriteNonNullableValueAsync(object value, Stream stream,
+            CancellationToken cancellationToken = default)
+        {
+            if (value == null) throw new IOException($"{nameof(value)} cannot be null");
+            var valueType = value.GetType();
+            var serializer = _registry.GetSerializerFor(valueType);
+            await serializer.WriteNonNullableValueAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
@@ -89,7 +100,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// <param name="stream">The stream to write to.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
-        public async Task WriteAsync(object value, Stream stream, CancellationToken cancellationToken = default)
+        public async Task WriteAsync(object? value, Stream stream, CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
@@ -103,7 +114,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             if (serializer is CustomTypeSerializer customTypeSerializer)
             {
                 await stream.WriteAsync(CustomTypeCodeBytes, cancellationToken).ConfigureAwait(false);
-                await WriteValueAsync(customTypeSerializer.TypeName, stream, false, cancellationToken)
+                await WriteNonNullableValueAsync(customTypeSerializer.TypeName, stream, cancellationToken)
                     .ConfigureAwait(false);
                 await customTypeSerializer.WriteAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
                 return;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs
index 6bbe52abac..40605dda2a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs
@@ -49,15 +49,25 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             CancellationToken cancellationToken = default);
 
         /// <summary>
-        /// Writes the value to a stream, composed by the value flag and the sequence of bytes.
+        /// Writes the nullable value to a stream, composed by the value flag and the sequence of bytes.
         /// </summary>
         /// <param name="value">The value to write.</param>
         /// <param name="stream">The stream to write to.</param>
         /// <param name="writer">A <see cref="GraphBinaryWriter"/> that can be used to write nested values.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
-        Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        Task WriteNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
+            CancellationToken cancellationToken = default);
+        
+        /// <summary>
+        /// Writes the non-nullable value to a stream, composed by the value flag and the sequence of bytes.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        /// <param name="stream">The stream to write to.</param>
+        /// <param name="writer">A <see cref="GraphBinaryWriter"/> that can be used to write nested values.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <returns>A task that represents the asynchronous write operation.</returns>
+        Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default);
 
         /// <summary>
@@ -67,17 +77,26 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
         /// <param name="reader">A <see cref="GraphBinaryReader"/> that can be used to read nested values.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The read value.</returns>
-        Task<object> ReadAsync(Stream stream, GraphBinaryReader reader, CancellationToken cancellationToken = default);
+        Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader, CancellationToken cancellationToken = default);
+
+        /// <summary>
+        /// Reads the value from the stream (not the type information).
+        /// </summary>
+        /// <param name="stream">The GraphBinary data to parse.</param>
+        /// <param name="reader">A <see cref="GraphBinaryReader"/> that can be used to read nested values.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <returns>The read value.</returns>
+        Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default);
 
         /// <summary>
         /// Reads the value from the stream (not the type information).
         /// </summary>
         /// <param name="stream">The GraphBinary data to parse.</param>
         /// <param name="reader">A <see cref="GraphBinaryReader"/> that can be used to read nested values.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The read value.</returns>
-        Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs
index e4bf380a15..8b489e1556 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs
@@ -45,13 +45,13 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             CancellationToken cancellationToken = default)
         {
             await stream.WriteByteAsync(GraphBinaryWriter.VersionByte, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.RequestId, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.RequestId, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.Operation, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.Operation, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.Processor, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.Processor, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.Arguments, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.Arguments, stream, cancellationToken)
                 .ConfigureAwait(false);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs
index 3a0fa6a1b6..e31c7a22a8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs
@@ -55,34 +55,23 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             }
 
             var requestId =
-                (Guid?)await reader.ReadValueAsync<Guid>(stream, true, cancellationToken).ConfigureAwait(false);
-            var code = (ResponseStatusCode)await reader.ReadValueAsync<int>(stream, false, cancellationToken)
+                (Guid?)await reader.ReadNullableValueAsync<Guid>(stream, cancellationToken).ConfigureAwait(false);
+            var code = (ResponseStatusCode)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken)
                 .ConfigureAwait(false);
-            var message = (string)await reader.ReadValueAsync<string>(stream, true, cancellationToken)
+            var message = (string?)await reader.ReadNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var dictObj = await reader
-                .ReadValueAsync<Dictionary<string, object>>(stream, false, cancellationToken).ConfigureAwait(false);
+                .ReadNonNullableValueAsync<Dictionary<string, object>>(stream, cancellationToken).ConfigureAwait(false);
             var attributes = (Dictionary<string, object>)dictObj;
 
-            var status = new ResponseStatus
-            {
-                Code = code,
-                Message = message,
-                Attributes = attributes
-            };
-            var result = new ResponseResult<List<object>>
-            {
-                Meta = (Dictionary<string, object>)await reader
-                    .ReadValueAsync<Dictionary<string, object>>(stream, false, cancellationToken).ConfigureAwait(false),
-                Data = (List<object>)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false)
-            };
+            var status = new ResponseStatus(code, attributes, message);
 
-            return new ResponseMessage<List<object>>
-            {
-                RequestId = requestId,
-                Status = status,
-                Result = result
-            };
+            var meta = (Dictionary<string, object>)await reader
+                .ReadNonNullableValueAsync<Dictionary<string, object>>(stream, cancellationToken).ConfigureAwait(false);
+            var data = (List<object>?)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var result = new ResponseResult<List<object>>(data, meta);
+
+            return new ResponseMessage<List<object>>(requestId, status, result);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
index f2ee3561ec..878152ba85 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
@@ -23,6 +23,8 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
 using System.Linq;
 using System.Numerics;
 using Gremlin.Net.Process.Traversal;
@@ -95,7 +97,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
                 {DataType.Float, SingleTypeSerializers.FloatSerializer},
                 {DataType.List, new ListSerializer<object>()},
                 {DataType.Map, new MapSerializer<object, object>()},
-                {DataType.Set, new SetSerializer<HashSet<object>, object>()},
+                {DataType.Set, new SetSerializer<HashSet<object?>, object>()},
                 {DataType.Uuid, new UuidSerializer()},
                 {DataType.Edge, new EdgeSerializer()},
                 {DataType.Path, new PathSerializer()},
@@ -169,8 +171,10 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             if (IsDictionaryType(valueType, out var dictKeyType, out var dictValueType))
             {
                 var serializerType = typeof(MapSerializer<,>).MakeGenericType(dictKeyType, dictValueType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the dictionary type {valueType}.");
                 return serializer;
             }
 
@@ -178,17 +182,21 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             {
                 var memberType = valueType.GetGenericArguments()[0];
                 var serializerType = typeof(SetSerializer<,>).MakeGenericType(valueType, memberType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the set type {valueType}.");
                 return serializer;
             }
 
             if (valueType.IsArray)
             {
                 var memberType = valueType.GetElementType();
-                var serializerType = typeof(ArraySerializer<>).MakeGenericType(memberType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializerType = typeof(ArraySerializer<>).MakeGenericType(memberType!);
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the array type {valueType}.");
                 return serializer;
             }
 
@@ -196,8 +204,10 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             {
                 var memberType = valueType.GetGenericArguments()[0];
                 var serializerType = typeof(ListSerializer<>).MakeGenericType(memberType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the list type {valueType}.");
                 return serializer;
             }
 
@@ -214,7 +224,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary
             throw new InvalidOperationException($"No serializer found for type ${valueType}.");
         }
 
-        private static bool IsDictionaryType(Type type, out Type keyType, out Type valueType)
+        private static bool IsDictionaryType(Type type, [NotNullWhen(returnValue: true)] out Type? keyType,
+            [NotNullWhen(returnValue: true)] out Type? valueType)
         {
             var maybeInterfaceType = type
                 .GetInterfaces()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs
index 4bd85f849a..01ef44be30 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs
@@ -45,7 +45,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(TMember[] value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Length, stream, cancellationToken).ConfigureAwait(false);
             
             foreach (var item in value)
             {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs
index 8a3cdc6e2c..f7fd205274 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs
@@ -46,8 +46,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var (unscaledValue, scale) = GetUnscaledValueAndScale(value);
-            await writer.WriteValueAsync(scale, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(unscaledValue, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(scale, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(unscaledValue, stream, cancellationToken).ConfigureAwait(false);
         }
         
         private static (BigInteger, int) GetUnscaledValueAndScale(decimal input)
@@ -79,8 +79,9 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<decimal> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var scale = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
-            var unscaled = (BigInteger)await reader.ReadValueAsync<BigInteger>(stream, false, cancellationToken)
+            var scale = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken)
+                .ConfigureAwait(false);
+            var unscaled = (BigInteger)await reader.ReadNonNullableValueAsync<BigInteger>(stream, cancellationToken)
                 .ConfigureAwait(false);
 
             return ConvertScaleAndUnscaledValue(scale, unscaled);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs
index efb67c5c10..08a2953cf2 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs
@@ -46,7 +46,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var bytes = value.ToByteArray().Reverse().ToArray();
-            await writer.WriteValueAsync(bytes.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(bytes.Length, stream, cancellationToken).ConfigureAwait(false);
             await stream.WriteAsync(bytes, cancellationToken).ConfigureAwait(false);
         }
 
@@ -54,7 +54,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<BigInteger> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var bytes = await stream.ReadAsync(length, cancellationToken).ConfigureAwait(false);
             return new BigInteger(bytes.Reverse().ToArray());
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs
index d7ed2832fc..87b884e912 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(Binding value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Key, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Key, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Value, stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,7 +52,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<Binding> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var key = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var key = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var value = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
             return new Binding(key, value);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs
index d1471ebc4f..6bf95cfcb0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs
@@ -56,13 +56,13 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<TList> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
 
             var result = new TList();
             for (var i = 0; i < length; i++)
             {
                 var value = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-                var bulk = (long)await reader.ReadValueAsync<long>(stream, false, cancellationToken)
+                var bulk = (long)await reader.ReadNonNullableValueAsync<long>(stream, cancellationToken)
                     .ConfigureAwait(false);
                 for (var j = 0; j < bulk; j++)
                 {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs
index e75550fd0c..ca658f127c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(byte[] value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Length, stream, cancellationToken).ConfigureAwait(false);
             await stream.WriteAsync(value, 0, value.Length, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,7 +52,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<byte[]> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var buffer = new byte[length];
             await stream.ReadAsync(buffer, 0, length, cancellationToken).ConfigureAwait(false);
             return buffer;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs
index e41146c4bd..3f043d1a34 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs
@@ -54,21 +54,21 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         private static async Task WriteInstructionsAsync(IReadOnlyCollection<Instruction> instructions, Stream stream,
             GraphBinaryWriter writer, CancellationToken cancellationToken)
         {
-            await writer.WriteValueAsync(instructions.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(instructions.Count, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var instruction in instructions)
             {
-                await writer.WriteValueAsync(instruction.OperatorName, stream, false, cancellationToken)
+                await writer.WriteNonNullableValueAsync(instruction.OperatorName, stream, cancellationToken)
                     .ConfigureAwait(false);
                 await WriteArgumentsAsync(instruction.Arguments, stream, writer, cancellationToken)
                     .ConfigureAwait(false);
             }
         }
 
-        private static async Task WriteArgumentsAsync(object[] arguments, Stream stream, GraphBinaryWriter writer,
+        private static async Task WriteArgumentsAsync(object?[] arguments, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken)
         {
-            await writer.WriteValueAsync(arguments.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(arguments.Length, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var value in arguments)
             {
@@ -82,11 +82,11 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         {
             var result = new Bytecode();
 
-            var stepsLength = (int) await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var stepsLength = (int) await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             for (var i = 0; i < stepsLength; i++)
             {
                 result.AddStep(
-                    (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                    (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                     await ReadArgumentsAsync(stream, reader, cancellationToken).ConfigureAwait(false));
             }
             
@@ -94,19 +94,19 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             for (var i = 0; i < sourcesLength; i++)
             {
                 result.AddSource(
-                    (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                    (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                     await ReadArgumentsAsync(stream, reader, cancellationToken).ConfigureAwait(false));
             }
             
             return result;
         }
 
-        private static async Task<object[]> ReadArgumentsAsync(Stream stream, GraphBinaryReader reader,
+        private static async Task<object?[]> ReadArgumentsAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken)
         {
             var valuesLength =
-                (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
-            var values = new object[valuesLength];
+                (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
+            var values = new object?[valuesLength];
             for (var i = 0; i < valuesLength; i++)
             {
                 values[i] = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs
index 55b932fc39..8dd1763a33 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs
@@ -45,7 +45,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(GremlinType value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Fqcn, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Fqcn, stream, cancellationToken).ConfigureAwait(false);
         }
 
         
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs
index 2721c05c2f..8b558eddd3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs
@@ -45,15 +45,23 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public abstract Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        public abstract Task WriteNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public abstract Task<object> ReadAsync(Stream stream, GraphBinaryReader reader,
+        public abstract Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public abstract Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        public abstract Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default);
+
+        /// <inheritdoc />
+        public abstract Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default);
+
+        /// <inheritdoc />
+        public abstract Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs
index eade891a95..e91cc85b9b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs
@@ -44,12 +44,12 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             await writer.WriteAsync(value.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Label, stream, cancellationToken).ConfigureAwait(false);
             
             await writer.WriteAsync(value.InV.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.InV.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.InV.Label, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.OutV.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.OutV.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.OutV.Label, stream, cancellationToken).ConfigureAwait(false);
 
             // Placeholder for the parent vertex
             await writer.WriteAsync(null, stream, cancellationToken).ConfigureAwait(false);
@@ -63,13 +63,13 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var id = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            var label = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var label = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
 
             var inV = new Vertex(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false));
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false));
             var outV = new Vertex(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false));
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false));
             
             // discard possible parent vertex
             await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
index 1d94235c0a..69e902d4f4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
@@ -127,7 +127,10 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<TEnum> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var enumValue = (string) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            // This should probably be `reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)` instead,
+            // but it's the same in other GLVs and changing this would be a breaking change for the GraphBinary format.
+            var enumValue = (string?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            if (enumValue == null) throw new IOException($"Read null as a value for {DataType}");
             return _readFunc.Invoke(enumValue);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs
index 7be1583da8..f017aeedb3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs
@@ -44,23 +44,23 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(ILambda value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Language, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.LambdaExpression, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(value.Language, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.LambdaExpression, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Arguments, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Arguments, stream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
         protected override async Task<ILambda> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var language = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var language = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
-            var expression = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var expression = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             
             // discard the arguments
-            await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
 
             return new StringBasedLambda(expression, language);
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs
index 05f96e6c34..d586ecd888 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs
@@ -32,7 +32,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
     /// A generic list serializer.
     /// </summary>
     /// <typeparam name="TMember">The type of elements in the list.</typeparam>
-    public class ListSerializer<TMember> : SimpleTypeSerializer<IList<TMember>>
+    public class ListSerializer<TMember> : SimpleTypeSerializer<IList<TMember?>>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="ListSerializer{TList}" /> class.
@@ -42,10 +42,10 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         }
 
         /// <inheritdoc />
-        protected override async Task WriteValueAsync(IList<TMember> value, Stream stream, GraphBinaryWriter writer,
+        protected override async Task WriteValueAsync(IList<TMember?> value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Count, stream, cancellationToken).ConfigureAwait(false);
             
             foreach (var item in value)
             {
@@ -54,14 +54,14 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         }
 
         /// <inheritdoc />
-        protected override async Task<IList<TMember>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
+        protected override async Task<IList<TMember?>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
-            var result = new List<TMember>(length);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
+            var result = new List<TMember?>(length);
             for (var i = 0; i < length; i++)
             {
-                result.Add((TMember) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
+                result.Add((TMember?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
             }
 
             return result;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs
index d22526f332..868155f573 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs
@@ -33,7 +33,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
     /// </summary>
     /// <typeparam name="TKey">The type of keys in the dictionary.</typeparam>
     /// <typeparam name="TValue">The type of values in the dictionary.</typeparam>
-    public class MapSerializer<TKey, TValue> : SimpleTypeSerializer<IDictionary<TKey, TValue>>
+    public class MapSerializer<TKey, TValue> : SimpleTypeSerializer<IDictionary<TKey, TValue?>> where TKey : notnull
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="MapSerializer{TKey, TValue}" /> class.
@@ -43,10 +43,10 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         }
 
         /// <inheritdoc />
-        protected override async Task WriteValueAsync(IDictionary<TKey, TValue> value, Stream stream,
+        protected override async Task WriteValueAsync(IDictionary<TKey, TValue?> value, Stream stream,
             GraphBinaryWriter writer, CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Count, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var key in value.Keys)
             {
@@ -56,16 +56,17 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         }
 
         /// <inheritdoc />
-        protected override async Task<IDictionary<TKey, TValue>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
+        protected override async Task<IDictionary<TKey, TValue?>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
             var length = await stream.ReadIntAsync(cancellationToken).ConfigureAwait(false);
-            var result = new Dictionary<TKey, TValue>(length);
+            var result = new Dictionary<TKey, TValue?>(length);
             
             for (var i = 0; i < length; i++)
             {
-                var key = (TKey) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-                var value = (TValue) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                var key = (TKey?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                if (key == null) throw new IOException("Read null as the key for a dictionary.");
+                var value = (TValue?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
                 result.Add(key, value);
             }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs
index 4579c6a102..d3cbddcea8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs
@@ -23,6 +23,7 @@
 
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -50,8 +51,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
 
             var argsLength = value.Other == null ? args.Count : args.Count + 1;
 
-            await writer.WriteValueAsync(value.OperatorName, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(argsLength, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.OperatorName, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(argsLength, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var arg in args)
             {
@@ -68,12 +69,12 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<P> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var operatorName = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var operatorName = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var argsLength =
-                (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+                (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
 
-            var args = new object[argsLength];
+            var args = new object?[argsLength];
             for (var i = 0; i < argsLength; i++)
             {
                 args[i] = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
@@ -82,23 +83,30 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             if (operatorName == "and" || operatorName == "or")
             {
                 
-                return new P(operatorName, (P) args[0], (P) args[1]);
+                return new P(operatorName, SafelyCastToP(args[0]), SafelyCastToP(args[1]));
             }
 
             if (operatorName == "not")
             {
-                return new P(operatorName, (P) args[0]);
+                return new P(operatorName, SafelyCastToP(args[0]));
             }
 
             if (argsLength == 1)
             {
                 if (DataType == DataType.TextP)
                 {
-                    return new TextP(operatorName, (string) args[0]);
+                    return new TextP(operatorName,
+                        (string?) args[0] ?? throw new IOException("Read null but expected a string"));
                 }
                 return new P(operatorName, args[0]);
             }
             return new P(operatorName, args);
         }
+        
+        private static P SafelyCastToP([NotNull] object? pObject)
+        {
+            if (pObject == null) throw new IOException("Read null but expected P");
+            return (P) pObject;
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs
index a9aba98ab4..fa02d5db6b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs
@@ -53,7 +53,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var readLabelObjects =
-                (List<object>)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                (List<object>?)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            if (readLabelObjects == null) throw new IOException("Read null, but expected a list of labels");
             var labels = new List<ISet<string>>();
             foreach (var labelObjectList in readLabelObjects)
             {
@@ -65,8 +66,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
                 labels.Add(labelSet);
             }
             
-            var objects = (List<object>) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            
+            var objects = (List<object?>?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            if (objects == null) throw new IOException("Read null, but expected a list of objects");
             return new Path(labels, objects);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs
index 08fc6e9a5e..556cd91697 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs
@@ -30,7 +30,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
     /// <summary>
     /// A <see cref="Property"/> serializer.
     /// </summary>
-    public class PropertySerializer : SimpleTypeSerializer<Property>
+    public class 
+        PropertySerializer : SimpleTypeSerializer<Property>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="PropertySerializer" /> class.
@@ -43,7 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(Property value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Key, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Key, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Value, stream, cancellationToken).ConfigureAwait(false);
             
             // placeholder for the parent element
@@ -55,7 +56,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var p = new Property(
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                 await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
 
             // discard parent element
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs
index 8983a4c2e5..92a3ddde3f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs
@@ -36,7 +36,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
     /// <typeparam name="TSet">The type of the set to serialize.</typeparam>
     /// <typeparam name="TMember">The type of elements in the set.</typeparam>
     public class SetSerializer<TSet, TMember> : SimpleTypeSerializer<TSet>
-        where TSet : ISet<TMember>, new()
+        where TSet : ISet<TMember?>, new()
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="SetSerializer{TSet,TMember}" /> class.
@@ -52,7 +52,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             var enumerable = (IEnumerable) value;
             var list = enumerable.Cast<object>().ToList();
 
-            await writer.WriteValueAsync(list.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(list.Count, stream, cancellationToken).ConfigureAwait(false);
             
             foreach (var item in list)
             {
@@ -64,11 +64,11 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<TSet> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var result = new TSet();
             for (var i = 0; i < length; i++)
             {
-                result.Add((TMember) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
+                result.Add((TMember?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
             }
 
             return result;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs
index cf6aa7bd9f..172fbe79fe 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs
@@ -46,34 +46,33 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         public DataType DataType { get; }
 
         /// <inheritdoc />
-        public async Task WriteAsync(object value, Stream stream, GraphBinaryWriter writer,
+        public async Task WriteAsync(object? value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await WriteValueAsync((T) value, stream, writer, true, cancellationToken).ConfigureAwait(false);
+            await WriteNullableValueAsync((T?) value, stream, writer, cancellationToken).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
-        public async Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        public async Task WriteNullableValueAsync(object? value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
-                if (!nullable)
-                {
-                    throw new IOException("Unexpected null value when nullable is false");
-                }
-
                 await writer.WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
                 return;
             }
 
-            if (nullable)
-            {
-                await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
-            }
+            await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
 
             await WriteValueAsync((T) value, stream, writer, cancellationToken).ConfigureAwait(false);
         }
+        
+        /// <inheritdoc />
+        public async Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
+            CancellationToken cancellationToken = default)
+        {
+            await WriteValueAsync((T) value, stream, writer, cancellationToken).ConfigureAwait(false);
+        }
 
         /// <summary>
         /// Writes a non-nullable value into a stream.
@@ -87,27 +86,31 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public async Task<object> ReadAsync(Stream stream, GraphBinaryReader reader,
+        public async Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            return await ReadValueAsync(stream, reader, true, cancellationToken).ConfigureAwait(false);
+            return await ReadNullableValueAsync(stream, reader, cancellationToken).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
-        public async Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        public async Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            if (nullable)
+            var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
+            if ((valueFlag & 1) == 1)
             {
-                var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
-                if ((valueFlag & 1) == 1)
-                {
-                    return null;
-                }
+                return null;
             }
 
             return await ReadValueAsync(stream, reader, cancellationToken).ConfigureAwait(false);
         }
+        
+        /// <inheritdoc />
+        public async Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default)
+        {
+            return (await ReadValueAsync(stream, reader, cancellationToken).ConfigureAwait(false))!;
+        }
 
         /// <summary>
         /// Reads a non-nullable value according to the type format.
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs
index ae2b9a1cd7..034230ab79 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs
@@ -45,7 +45,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var bytes = Encoding.UTF8.GetBytes(value);
-            await writer.WriteValueAsync(bytes.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(bytes.Length, stream, cancellationToken).ConfigureAwait(false);
             await stream.WriteAsync(bytes, cancellationToken).ConfigureAwait(false);
         }
 
@@ -53,7 +53,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<string> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var bytes = new byte[length];
             await stream.ReadAsync(bytes, 0, length, cancellationToken).ConfigureAwait(false);
             return Encoding.UTF8.GetString(bytes);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs
index 0b6ba0a93e..1e00047534 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs
@@ -45,7 +45,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(ITraversal value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Bytecode, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Bytecode, stream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs
index 6d7f537748..24077fa51c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs
@@ -45,9 +45,9 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(AbstractTraversalStrategy value, Stream stream,
             GraphBinaryWriter writer, CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(GremlinType.FromFqcn(value.Fqcn), stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(GremlinType.FromFqcn(value.Fqcn), stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Configuration, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Configuration, stream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs
index 12ba016b7b..9be8a0cfce 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task WriteValueAsync(Traverser value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Bulk, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Bulk, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Object, stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,7 +52,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         protected override async Task<Traverser> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var bulk = (long)await reader.ReadValueAsync<long>(stream, false, cancellationToken).ConfigureAwait(false);
+            var bulk = (long)await reader.ReadNonNullableValueAsync<long>(stream, cancellationToken).ConfigureAwait(false);
             var v = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
             return new Traverser(v, bulk);
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs
index c02ba0e885..51793daba6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs
@@ -48,8 +48,10 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         {
             if (typeof(AbstractTraversalStrategy).IsAssignableFrom(value))
             {
-                var strategyInstance = (AbstractTraversalStrategy) Activator.CreateInstance(value);
-                await writer.WriteValueAsync(strategyInstance.Fqcn, stream, false, cancellationToken)
+                var strategyInstance = (AbstractTraversalStrategy?)Activator.CreateInstance(value) ??
+                                       throw new IOException(
+                                           $"Cannot write the strategy {value} because an instance of that strategy could not be created");
+                await writer.WriteNonNullableValueAsync(strategyInstance.Fqcn, stream, cancellationToken)
                     .ConfigureAwait(false);
             }
             else
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs
index bc146dcc09..f9867795e1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             await writer.WriteAsync(value.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Label, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Value, stream, cancellationToken).ConfigureAwait(false);
             
             // placeholder for the parent vertex
@@ -60,7 +60,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             var vp = new VertexProperty(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                 await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
 
             // discard the parent vertex
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs
index c656431ae5..f339407877 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs
@@ -44,7 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
             CancellationToken cancellationToken = default)
         {
             await writer.WriteAsync(value.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Label, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(null, stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -54,7 +54,7 @@ namespace Gremlin.Net.Structure.IO.GraphBinary.Types
         {
 
             var v = new Vertex(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false));
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false));
             
             // discard properties
             await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
index a3f1ff6f72..36ea1fd4ca 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Numerics;
 using System.Text.Json;
 
@@ -31,6 +32,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         public dynamic Objectify(JsonElement graphson, GraphSONReader reader)
         {
             var bigInteger = graphson.ValueKind == JsonValueKind.String ? graphson.GetString() : graphson.GetRawText();
+            if (bigInteger == null) throw new IOException("Read null, but expected a BigInteger string representation");
             return BigInteger.Parse(bigInteger);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
index 539224a347..8f876b6b19 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
@@ -42,7 +42,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             // previous versions.
             return Enumerable.Range(0, graphsonObject.GetArrayLength() / 2).SelectMany<int, object>(i =>
                 Enumerable.Repeat<object>(reader.ToObject(graphsonObject[i * 2]),
-                    (int) reader.ToObject(graphsonObject[i * 2 + 1]))).ToList();
+                    (int) reader.ToObject(graphsonObject[i * 2 + 1])!)).ToList();
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
index 0feb3a297a..adb4efa103 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
@@ -21,6 +21,7 @@
 #endregion
 
 using System;
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -30,7 +31,8 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var base64String = graphsonObject.GetString();
-            return Convert.FromBase64String(base64String);
+            return Convert.FromBase64String(base64String ??
+                                            throw new IOException("Read null but expected a base64 byte string"));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
index 0c3e53991f..b86cf155f3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
@@ -20,6 +20,7 @@
  */
 #endregion
 
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -31,7 +32,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         protected override bool StringifyValue => true;
         protected override dynamic FromJsonElement(JsonElement graphson)
         {
-            var deserializedByte = graphson.GetString();
+            var deserializedByte = graphson.GetString() ?? throw new IOException("Read null but expected a string");
             return deserializedByte[0];
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs
index 39d1abe65b..8bd73530ca 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -31,7 +32,8 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
         {
             var type = (Type) objectData;
-            return writer.ToDict(Activator.CreateInstance(type));
+            return writer.ToDict(Activator.CreateInstance(type) ??
+                                 throw new IOException($"Cannot write {objectData}. maybe it is not a supported type"));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
index f1955227d0..b4167a6546 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Globalization;
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -35,7 +36,9 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         {
             if (graphson.ValueKind == JsonValueKind.String)
             {
-                return decimal.Parse(graphson.GetString(), CultureInfo.InvariantCulture);
+                return decimal.Parse(
+                    graphson.GetString() ?? throw new IOException("Read null but expected a decimal string"),
+                    CultureInfo.InvariantCulture);
             }
             return graphson.GetDecimal();
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
index 34d4f61b66..68351696b1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 
@@ -30,7 +31,9 @@ namespace Gremlin.Net.Structure.IO.GraphSON
     {
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return Direction.GetByValue(graphsonObject.GetString());
+            return Direction.GetByValue(graphsonObject.GetString() ??
+                                        throw new IOException(
+                                            $"Read null but expected a {nameof(Direction)} string representation"));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
index 2c1d17fc11..e23c7a5fc7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using System.Xml;
 
@@ -31,7 +32,9 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var duration = graphsonObject.GetString();
-            return XmlConvert.ToTimeSpan(duration);
+            return XmlConvert.ToTimeSpan(duration ??
+                                         throw new IOException(
+                                             "Read null but expected a Duration string representation"));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs
index c0c36b1dd6..7f9d7bd548 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         /// </summary>
         /// <param name="graphSONReader">The <see cref="GraphSON2Reader"/> used to deserialize from GraphSON.</param>
         /// <param name="graphSONWriter">The <see cref="GraphSON2Writer"/> used to serialize to GraphSON.</param>
-        public GraphSON2MessageSerializer(GraphSON2Reader graphSONReader = null, GraphSON2Writer graphSONWriter = null)
+        public GraphSON2MessageSerializer(GraphSON2Reader? graphSONReader = null, GraphSON2Writer? graphSONWriter = null)
             : base(MimeType, graphSONReader ?? new GraphSON2Reader(), graphSONWriter ?? new GraphSON2Writer())
         {
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs
index abb6a750f5..bc434c776b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         /// </summary>
         /// <param name="graphSONReader">The <see cref="GraphSON3Reader"/> used to deserialize from GraphSON.</param>
         /// <param name="graphSONWriter">The <see cref="GraphSON3Writer"/> used to serialize to GraphSON.</param>
-        public GraphSON3MessageSerializer(GraphSON3Reader graphSONReader = null, GraphSON3Writer graphSONWriter = null)
+        public GraphSON3MessageSerializer(GraphSON3Reader? graphSONReader = null, GraphSON3Writer? graphSONWriter = null)
             : base(MimeType, graphSONReader ?? new GraphSON3Reader(), graphSONWriter ?? new GraphSON3Writer())
         {
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs
index 4d4ffa17fa..c9f2b881f6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Text;
 using System.Text.Json;
 using System.Threading;
@@ -72,17 +73,17 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         }
 
         /// <inheritdoc />
-        public virtual Task<ResponseMessage<List<object>>> DeserializeMessageAsync(byte[] message,
+        public virtual Task<ResponseMessage<List<object>>?> DeserializeMessageAsync(byte[] message,
             CancellationToken cancellationToken = default)
         {
             if (message == null) throw new ArgumentNullException(nameof(message));
             if (cancellationToken.CanBeCanceled) cancellationToken.ThrowIfCancellationRequested();
-            if (message.Length == 0) return Task.FromResult<ResponseMessage<List<object>>>(null);
+            if (message.Length == 0) return Task.FromResult<ResponseMessage<List<object>>?>(null);
             
             var reader = new Utf8JsonReader(message);
             var responseMessage =
                 JsonSerializer.Deserialize<ResponseMessage<JsonElement>>(ref reader, JsonDeserializingOptions);
-            if (responseMessage == null) return Task.FromResult<ResponseMessage<List<object>>>(null);;
+            if (responseMessage == null) return Task.FromResult<ResponseMessage<List<object>>?>(null);
             
             var data = _graphSONReader.ToObject(responseMessage.Result.Data);
             return Task.FromResult(CopyMessageWithNewData(responseMessage, data));
@@ -91,16 +92,9 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         private static ResponseMessage<List<object>> CopyMessageWithNewData(ResponseMessage<JsonElement> origMsg,
             dynamic data)
         {
-            return new ResponseMessage<List<object>>
-            {
-                RequestId = origMsg.RequestId,
-                Status = origMsg.Status,
-                Result = new ResponseResult<List<object>>
-                {
-                    Data = data == null ? null : new List<object>(data),
-                    Meta = origMsg.Result.Meta
-                }
-            };
+            var result = new ResponseResult<List<object>>(data == null ? null : new List<object>(data),
+                origMsg.Result.Meta);
+            return new ResponseMessage<List<object>>(origMsg.RequestId, origMsg.Status, result);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
index 32089665f1..3e09ec3a28 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.Json;
 
@@ -36,35 +37,34 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         /// <summary>
         /// Contains the <see cref="IGraphSONDeserializer" /> instances by their type identifier. 
         /// </summary>
-        protected readonly Dictionary<string, IGraphSONDeserializer> Deserializers = new Dictionary
-            <string, IGraphSONDeserializer>
-            {
-                {"g:Traverser", new TraverserReader()},
-                {"g:Int32", new Int32Converter()},
-                {"g:Int64", new Int64Converter()},
-                {"g:Float", new FloatConverter()},
-                {"g:Double", new DoubleConverter()},
-                {"g:Direction", new DirectionDeserializer()},
-                {"g:Merge", new MergeDeserializer()},
-                {"g:UUID", new UuidDeserializer()},
-                {"g:Date", new DateDeserializer()},
-                {"g:Timestamp", new DateDeserializer()},
-                {"g:Vertex", new VertexDeserializer()},
-                {"g:Edge", new EdgeDeserializer()},
-                {"g:Property", new PropertyDeserializer()},
-                {"g:VertexProperty", new VertexPropertyDeserializer()},
-                {"g:Path", new PathDeserializer()},
-                {"g:T", new TDeserializer()},
+        protected readonly Dictionary<string, IGraphSONDeserializer> Deserializers = new()
+        {
+            { "g:Traverser", new TraverserReader() },
+            { "g:Int32", new Int32Converter() },
+            { "g:Int64", new Int64Converter() },
+            { "g:Float", new FloatConverter() },
+            { "g:Double", new DoubleConverter() },
+            { "g:Direction", new DirectionDeserializer() },
+            { "g:Merge", new MergeDeserializer() },
+            { "g:UUID", new UuidDeserializer() },
+            { "g:Date", new DateDeserializer() },
+            { "g:Timestamp", new DateDeserializer() },
+            { "g:Vertex", new VertexDeserializer() },
+            { "g:Edge", new EdgeDeserializer() },
+            { "g:Property", new PropertyDeserializer() },
+            { "g:VertexProperty", new VertexPropertyDeserializer() },
+            { "g:Path", new PathDeserializer() },
+            { "g:T", new TDeserializer() },
 
-                //Extended
-                {"gx:BigDecimal", new DecimalConverter()},
-                {"gx:Duration", new DurationDeserializer()},
-                {"gx:BigInteger", new BigIntegerDeserializer()},
-                {"gx:Byte", new ByteConverter()},
-                {"gx:ByteBuffer", new ByteBufferDeserializer()},
-                {"gx:Char", new CharConverter()},
-                {"gx:Int16", new Int16Converter() }
-            };
+            //Extended
+            { "gx:BigDecimal", new DecimalConverter() },
+            { "gx:Duration", new DurationDeserializer() },
+            { "gx:BigInteger", new BigIntegerDeserializer() },
+            { "gx:Byte", new ByteConverter() },
+            { "gx:ByteBuffer", new ByteBufferDeserializer() },
+            { "gx:Char", new CharConverter() },
+            { "gx:Int16", new Int16Converter() }
+        };
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="GraphSONReader" /> class.
@@ -101,7 +101,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         /// </summary>
         /// <param name="graphSon">The GraphSON to deserialize.</param>
         /// <returns>The deserialized object.</returns>
-        public virtual dynamic ToObject(JsonElement graphSon)
+        public virtual dynamic? ToObject(JsonElement graphSon)
         {
             switch (graphSon.ValueKind)
             {
@@ -124,7 +124,9 @@ namespace Gremlin.Net.Structure.IO.GraphSON
 
             if (graphSon.TryGetProperty(GraphSONTokens.TypeKey, out var graphSonTypeProperty))
             {
-                return ReadValueOfType(graphSon, graphSonTypeProperty.GetString());
+                return ReadValueOfType(graphSon,
+                    graphSonTypeProperty.GetString() ??
+                    throw new IOException("Read GraphSON type key is not a string"));
             }
             return ReadDictionary(graphSon);
             
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
index e453efc792..5b1725ffce 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Numerics;
 using System.Text.Encodings.Web;
@@ -39,45 +40,44 @@ namespace Gremlin.Net.Structure.IO.GraphSON
     /// </summary>
     public abstract class GraphSONWriter
     {
-        private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
-            {Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping};
-        
+        private static readonly JsonSerializerOptions JsonOptions = new()
+            { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping };
+
         /// <summary>
         /// Contains the information of serializers by type.
         /// </summary>
-        protected readonly Dictionary<Type, IGraphSONSerializer> Serializers = new Dictionary
-            <Type, IGraphSONSerializer>
-            {
-                {typeof(ITraversal), new TraversalSerializer()},
-                {typeof(Bytecode), new BytecodeSerializer()},
-                {typeof(Binding), new BindingSerializer()},
-                {typeof(RequestMessage), new RequestMessageSerializer()},
-                {typeof(int), new Int32Converter()},
-                {typeof(long), new Int64Converter()},
-                {typeof(float), new FloatConverter()},
-                {typeof(double), new DoubleConverter()},
-                {typeof(Guid), new UuidSerializer()},
-                {typeof(DateTimeOffset), new DateSerializer()},
-                {typeof(Type), new ClassSerializer()},
-                {typeof(EnumWrapper), new EnumSerializer()},
-                {typeof(P), new PSerializer()},
-                {typeof(TextP), new TextPSerializer()},
-                {typeof(Vertex), new VertexSerializer()},
-                {typeof(Edge), new EdgeSerializer()},
-                {typeof(Property), new PropertySerializer()},
-                {typeof(VertexProperty), new VertexPropertySerializer()},
-                {typeof(AbstractTraversalStrategy), new TraversalStrategySerializer()},
-                {typeof(ILambda), new LambdaSerializer()},
-
-                //Extended
-                {typeof(decimal), new DecimalConverter()},
-                {typeof(TimeSpan), new DurationSerializer()},
-                {typeof(BigInteger), new BigIntegerSerializer()},
-                {typeof(byte), new ByteConverter()},
-                {typeof(byte[]), new ByteBufferSerializer()},
-                {typeof(char), new CharConverter() },
-                {typeof(short), new Int16Converter() }
-            };
+        protected readonly Dictionary<Type, IGraphSONSerializer> Serializers = new()
+        {
+            { typeof(ITraversal), new TraversalSerializer() },
+            { typeof(Bytecode), new BytecodeSerializer() },
+            { typeof(Binding), new BindingSerializer() },
+            { typeof(RequestMessage), new RequestMessageSerializer() },
+            { typeof(int), new Int32Converter() },
+            { typeof(long), new Int64Converter() },
+            { typeof(float), new FloatConverter() },
+            { typeof(double), new DoubleConverter() },
+            { typeof(Guid), new UuidSerializer() },
+            { typeof(DateTimeOffset), new DateSerializer() },
+            { typeof(Type), new ClassSerializer() },
+            { typeof(EnumWrapper), new EnumSerializer() },
+            { typeof(P), new PSerializer() },
+            { typeof(TextP), new TextPSerializer() },
+            { typeof(Vertex), new VertexSerializer() },
+            { typeof(Edge), new EdgeSerializer() },
+            { typeof(Property), new PropertySerializer() },
+            { typeof(VertexProperty), new VertexPropertySerializer() },
+            { typeof(AbstractTraversalStrategy), new TraversalStrategySerializer() },
+            { typeof(ILambda), new LambdaSerializer() },
+
+            //Extended
+            { typeof(decimal), new DecimalConverter() },
+            { typeof(TimeSpan), new DurationSerializer() },
+            { typeof(BigInteger), new BigIntegerSerializer() },
+            { typeof(byte), new ByteConverter() },
+            { typeof(byte[]), new ByteBufferSerializer() },
+            { typeof(char), new CharConverter() },
+            { typeof(short), new Int16Converter() }
+        };
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="GraphSONWriter" /> class.
@@ -106,7 +106,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         /// <returns>The serialized GraphSON.</returns>
         public virtual string WriteObject(dynamic objectData)
         {
-            return JsonSerializer.Serialize(ToDict(objectData), _jsonOptions);
+            return JsonSerializer.Serialize(ToDict(objectData), JsonOptions);
         }
 
         /// <summary>
@@ -114,7 +114,8 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         /// </summary>
         /// <param name="objectData">The object to transform.</param>
         /// <returns>A GraphSON representation of the object ready to be serialized.</returns>
-        public dynamic ToDict(dynamic objectData)
+        [return: NotNullIfNotNull("objectData")]
+        public dynamic? ToDict(dynamic? objectData)
         {
             if (objectData != null)
             {
@@ -132,7 +133,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             return objectData;         
         }
 
-        private IGraphSONSerializer TryGetSerializerFor(Type type)
+        private IGraphSONSerializer? TryGetSerializerFor(Type type)
         {
             if (Serializers.ContainsKey(type))
             {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
index add8eb569d..154010a813 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Text.Json;
 
@@ -28,7 +29,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
 {
     internal class ListSerializer : IGraphSONDeserializer, IGraphSONSerializer
     {
-        private static readonly IReadOnlyList<object> EmptyList = new object[0];
+        private static readonly IReadOnlyList<object> EmptyList = Array.Empty<object>();
         
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
@@ -36,7 +37,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             {
                 return EmptyList;
             }
-            var result = new object[graphsonObject.GetArrayLength()];
+            var result = new object?[graphsonObject.GetArrayLength()];
             for (var i = 0; i < result.Length; i++)
             {
                 result[i] = reader.ToObject(graphsonObject[i]);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
index 99165a7ced..3ba7e3ac96 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
@@ -36,7 +36,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             {
                 return new Dictionary<object, object>(0);
             }
-            var result = new Dictionary<object, object>(graphsonObject.GetArrayLength() / 2);
+            var result = new Dictionary<object, object?>(graphsonObject.GetArrayLength() / 2);
             for (var i = 0; i < graphsonObject.GetArrayLength(); i += 2)
             {
                 result[reader.ToObject(graphsonObject[i])] = reader.ToObject(graphsonObject[i + 1]);
@@ -51,7 +51,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             {
                 throw new InvalidOperationException("Object must implement IDictionary");
             }
-            var result = new object[map.Count * 2];
+            var result = new object?[map.Count * 2];
             var index = 0;
             foreach (var key in map.Keys)
             {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
index 26b6869177..3a34eb94fb 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 
@@ -30,7 +31,8 @@ namespace Gremlin.Net.Structure.IO.GraphSON
     {
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return Merge.GetByValue(graphsonObject.GetString());
+            return Merge.GetByValue(graphsonObject.GetString() ??
+                                    throw new IOException("Read null but expected a Merge value"));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
index 4492685def..b12c494f6d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
@@ -27,7 +27,7 @@ using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal abstract class NumberConverter<T> : IGraphSONDeserializer, IGraphSONSerializer
+    internal abstract class NumberConverter<T> : IGraphSONDeserializer, IGraphSONSerializer where T : notnull
     {
         protected abstract string GraphSONTypeName { get; }
         protected virtual string Prefix => "g";
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
index d05663bfca..6e353210e9 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.Json;
 
@@ -32,12 +33,14 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             // "labels" is a object[] where each item is ISet<object>
-            var labelProperty = (object[])reader.ToObject(graphsonObject.GetProperty("labels"));
+            var labelProperty = (object[]?)reader.ToObject(graphsonObject.GetProperty("labels"));
+            if (labelProperty == null) throw new IOException($"Could not read the labels for the {nameof(Path)}");
             var labels = labelProperty
                 .Select(x => new HashSet<string>(((ISet<object>)x).Cast<string>()))
                 .ToList<ISet<string>>();
             // "objects" is an object[]
-            object[] objects = reader.ToObject(graphsonObject.GetProperty("objects"));
+            object?[] objects = reader.ToObject(graphsonObject.GetProperty("objects")) ??
+                               throw new IOException($"Could not read the objects for the {nameof(Path)}");
             return new Path(labels, objects);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
index 3a37f66871..baa9722a20 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.Json;
 
@@ -34,7 +35,8 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             var labels =
                 graphsonObject.GetProperty("labels").EnumerateArray()
                     .Select(readObjLabels =>
-                        new HashSet<string>(readObjLabels.EnumerateArray().Select(l => l.GetString())))
+                        new HashSet<string>(readObjLabels.EnumerateArray().Select(l =>
+                            l.GetString() ?? throw new IOException("Read null but expected a Path label"))))
                     .ToList<ISet<string>>();
             var objects = graphsonObject.GetProperty("objects").EnumerateArray().Select(o => reader.ToObject(o))
                 .ToList();
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs
index 0a7e6f89a3..d668442d78 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Collections.Generic;
+using System.IO;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -40,23 +41,25 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             return GraphSONUtil.ToTypedValue(nameof(Property), valueDict);
         }
 
-        private dynamic CreateElementDict(Element element, GraphSONWriter writer)
+        private dynamic? CreateElementDict(Element? element, GraphSONWriter writer)
         {
             if (element == null)
                 return null;
             var serializedElement = writer.ToDict(element);
+            if (serializedElement == null)
+            {
+                throw new IOException(
+                    $"Could not write the {nameof(Property.Element)} of this {nameof(Property)}, {nameof(Property.Element)}: {element}");
+            }
             Dictionary<string, dynamic> elementDict = serializedElement;
             if (elementDict.ContainsKey(GraphSONTokens.ValueKey))
             {
                 var elementValueSerialized = elementDict[GraphSONTokens.ValueKey];
                 Dictionary<string, dynamic> elementValueDict = elementValueSerialized;
-                if (elementValueDict != null)
-                {
-                    elementValueDict.Remove("outVLabel");
-                    elementValueDict.Remove("inVLabel");
-                    elementValueDict.Remove("properties");
-                    elementValueDict.Remove("value");
-                }
+                elementValueDict.Remove("outVLabel");
+                elementValueDict.Remove("inVLabel");
+                elementValueDict.Remove("properties");
+                elementValueDict.Remove("value");
             }
             return serializedElement;
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
index 590392e30d..fce74658dd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
@@ -36,7 +36,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 return new HashSet<object>();
             }
             // ISet<object>
-            return new HashSet<object>(graphsonObject.EnumerateArray().Select(reader.ToObject));
+            return new HashSet<object?>(graphsonObject.EnumerateArray().Select(reader.ToObject));
         }
 
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
index efbc54242e..270d36a14a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 
@@ -30,7 +31,8 @@ namespace Gremlin.Net.Structure.IO.GraphSON
     {
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return T.GetByValue(graphsonObject.GetString());
+            return T.GetByValue(graphsonObject.GetString()??
+                                throw new IOException($"Read null but expected a {nameof(T)} string representation"));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
index 58caac7133..8e64236a5f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System;
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -31,7 +32,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var uuidString = graphsonObject.GetString();
-
+            if (uuidString == null) throw new IOException("Read null but expected a GUID string representation");
             return Guid.Parse(uuidString);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs
index 12cc7ac2cf..6000d35ebf 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs
@@ -34,9 +34,12 @@ namespace Gremlin.Net.Structure.IO.GraphSON
             {
                 {"id", writer.ToDict(vertexProperty.Id)},
                 {"label", vertexProperty.Label},
-                {"value", writer.ToDict(vertexProperty.Value)},
-                {"vertex", writer.ToDict(vertexProperty.Vertex.Id)}
+                {"value", writer.ToDict(vertexProperty.Value)}
             };
+            if (vertexProperty.Vertex != null)
+            {
+                valueDict.Add("vertex", writer.ToDict(vertexProperty.Vertex.Id));
+            }
             return GraphSONUtil.ToTypedValue(nameof(VertexProperty), valueDict);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs
index d205a88d0c..682aad3ca3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Gremlin.Net.Process.Traversal;
 
@@ -36,17 +37,17 @@ namespace Gremlin.Net.Structure
     ///     In abstraction, any Path implementation maintains two lists: a list of sets of labels and a list of objects.
     ///     The list of labels are the labels of the steps traversed. The list of objects are the objects traversed.
     /// </remarks>
-    public class Path : IReadOnlyList<object>, IEquatable<Path>
+    public class Path : IReadOnlyList<object?>, IEquatable<Path>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="Path" /> class.
         /// </summary>
         /// <param name="labels">The labels associated with the path</param>
         /// <param name="objects">The objects in the <see cref="Path" />.</param>
-        public Path(IList<ISet<string>> labels, IList<object> objects)
+        public Path(IList<ISet<string>> labels, IList<object?> objects)
         {
-            Labels = labels;
-            Objects = objects;
+            Labels = labels ?? throw new ArgumentNullException(nameof(labels));
+            Objects = objects ?? throw new ArgumentNullException(nameof(objects));
         }
 
         /// <summary>
@@ -57,7 +58,7 @@ namespace Gremlin.Net.Structure
         /// <summary>
         ///     Gets an ordered list of the objects in the <see cref="Path" />.
         /// </summary>
-        public IList<object> Objects { get; }
+        public IList<object?> Objects { get; }
 
         /// <summary>
         ///     Gets the object associated with the particular label of the path.
@@ -70,15 +71,15 @@ namespace Gremlin.Net.Structure
         {
             get
             {
-                var objFound = TryGetValue(label, out object obj);
+                var objFound = TryGetValue(label, out var obj);
                 if (!objFound)
                     throw new KeyNotFoundException($"The step with label {label} does not exist");
-                return obj;
+                return obj!;
             }
         }
 
         /// <inheritdoc />
-        public bool Equals(Path other)
+        public bool Equals(Path? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -90,7 +91,7 @@ namespace Gremlin.Net.Structure
         /// </summary>
         /// <param name="index">The index of the path</param>
         /// <returns>The object associated with the index of the path</returns>
-        public dynamic this[int index] => Objects[index];
+        public dynamic? this[int index] => Objects[index];
 
         /// <summary>
         ///     Gets the number of steps in the path.
@@ -131,7 +132,7 @@ namespace Gremlin.Net.Structure
         /// <param name="label">The label of the path.</param>
         /// <param name="value">The object associated with the label of the path.</param>
         /// <returns>True, if an object was found for the label.</returns>
-        public bool TryGetValue(string label, out object value)
+        public bool TryGetValue(string label, [NotNullWhen(true)] out object? value)
         {
             value = null;
             for (var i = 0; i < Labels.Count; i++)
@@ -139,43 +140,38 @@ namespace Gremlin.Net.Structure
                 if (!Labels[i].Contains(label)) continue;
                 if (value == null)
                     value = Objects[i];
-                else if (value.GetType() == typeof(List<object>))
-                    ((List<object>) value).Add(Objects[i]);
+                else if (value.GetType() == typeof(List<object?>))
+                    ((List<object?>) value).Add(Objects[i]);
                 else
-                    value = new List<object> {value, Objects[i]};
+                    value = new List<object?> {value, Objects[i]};
             }
             return value != null;
         }
 
-        private bool ObjectsEqual(ICollection<object> otherObjects)
+        private bool ObjectsEqual(ICollection<object?> otherObjects)
         {
-            if (Objects == null)
-                return otherObjects == null;
             return Objects.SequenceEqual(otherObjects);
         }
 
         private bool LabelsEqual(ICollection<ISet<string>> otherLabels)
         {
-            if (Labels == null)
-                return otherLabels == null;
             if (Labels.Count != otherLabels.Count)
                 return false;
-            using (var enumOther = otherLabels.GetEnumerator())
-            using (var enumThis = Labels.GetEnumerator())
+            using var enumOther = otherLabels.GetEnumerator();
+            using var enumThis = Labels.GetEnumerator();
+            while (enumOther.MoveNext() && enumThis.MoveNext())
             {
-                while (enumOther.MoveNext() && enumThis.MoveNext())
+                if (!enumOther.Current.SequenceEqual(enumThis.Current))
                 {
-                    if (!enumOther.Current.SequenceEqual(enumThis.Current))
-                    {
-                        return false;
-                    }
+                    return false;
                 }
             }
+
             return true;
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -189,13 +185,12 @@ namespace Gremlin.Net.Structure
             unchecked
             {
                 var hashCode = 19;
-                if (Labels != null)
-                    hashCode = Labels.Where(objLabels => objLabels != null)
-                        .Aggregate(hashCode,
-                            (current1, objLabels) => objLabels.Aggregate(current1,
-                                (current, label) => current * 31 + label.GetHashCode()));
-                if (Objects != null)
-                    hashCode = Objects.Aggregate(hashCode, (current, obj) => current * 31 + obj.GetHashCode());
+                hashCode = Labels
+                    .Aggregate(hashCode,
+                        (current1, objLabels) => objLabels.Aggregate(current1,
+                            (current, label) => current * 31 + label.GetHashCode()));
+                hashCode = Objects.Aggregate(hashCode,
+                    (current, obj) => current * 31 + (obj == null ? 0 : obj.GetHashCode()));
                 return hashCode;
             }
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs
index b2adee760b..291287d9de 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs
@@ -36,7 +36,7 @@ namespace Gremlin.Net.Structure
         /// <param name="key">The key of the property.</param>
         /// <param name="value">The value of the property.</param>
         /// <param name="element">The (optional) element that the property is associated with.</param>
-        public Property(string key, dynamic value, Element element = null)
+        public Property(string key, dynamic? value, Element? element = null)
         {
             Key = key;
             Value = value;
@@ -51,15 +51,15 @@ namespace Gremlin.Net.Structure
         /// <summary>
         ///     Gets the value of the property.
         /// </summary>
-        public dynamic Value { get; }
+        public dynamic? Value { get; }
 
         /// <summary>
         ///     Gets the element that this property is associated with.
         /// </summary>
-        public Element Element { get; }
+        public Element? Element { get; }
 
         /// <inheritdoc />
-        public bool Equals(Property other)
+        public bool Equals(Property? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -73,7 +73,7 @@ namespace Gremlin.Net.Structure
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs
index f667d26f30..b48fe15fe2 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs
@@ -38,7 +38,7 @@ namespace Gremlin.Net.Structure
         /// </summary>
         /// <param name="id">The id of the vertex.</param>
         /// <param name="label">The label of the vertex.</param>
-        public Vertex(object id, string label = DefaultLabel)
+        public Vertex(object? id, string label = DefaultLabel)
             : base(id, label)
         {
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs
index a8dd943484..a01aaa9705 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs
@@ -35,7 +35,7 @@ namespace Gremlin.Net.Structure
         /// <param name="label">The label of the vertex property.</param>
         /// <param name="value">The id of the vertex property.</param>
         /// <param name="vertex">The (optional) <see cref="Vertex" /> that owns this <see cref="VertexProperty" />.</param>
-        public VertexProperty(object id, string label, dynamic value, Vertex vertex = null)
+        public VertexProperty(object? id, string label, dynamic? value, Vertex? vertex = null)
             : base(id, label)
         {
             Value = value;
@@ -45,12 +45,12 @@ namespace Gremlin.Net.Structure
         /// <summary>
         ///     The value of this <see cref="VertexProperty" />.
         /// </summary>
-        public dynamic Value { get; }
+        public dynamic? Value { get; }
 
         /// <summary>
         ///     The <see cref="Vertex" /> that owns this <see cref="VertexProperty" />.
         /// </summary>
-        public Vertex Vertex { get; }
+        public Vertex? Vertex { get; }
 
         /// <summary>
         ///     The key of this <see cref="VertexProperty" />.
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
index f01116d0eb..ca363191c2 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
@@ -93,5 +93,7 @@ namespace Gremlin.Net.IntegrationTest.Process.Remote
             TraversalStrategies.Add(traversalStrategy);
             Bytecode = bytecode;
         }
+
+        public override Bytecode Bytecode { get; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs
index 44c7105ba2..f912f6a8fb 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs
@@ -294,10 +294,8 @@ namespace Gremlin.Net.UnitTest.Driver
             var fakeMessageSerializer = new Mock<IMessageSerializer>();
             var receivedBytes = new byte[] { 1, 2, 3 };
             var messageToCancel = RequestMessage.Build(string.Empty).Create();
-            var receivedMessage = new ResponseMessage<List<object>>
-            {
-                RequestId = messageToCancel.RequestId, Status = new ResponseStatus { Code = ResponseStatusCode.Success }
-            };
+            var receivedMessage = new ResponseMessage<List<object>>(messageToCancel.RequestId,
+                new ResponseStatus(ResponseStatusCode.Success), new ResponseResult<List<object>>(null));
             fakeMessageSerializer.Setup(f => f.DeserializeMessageAsync(receivedBytes, It.IsAny<CancellationToken>()))
                 .ReturnsAsync(receivedMessage);
             var fakeWebSocketConnection = new Mock<IWebSocketConnection>();
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs
index 51aac86387..0356ff4db7 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs
@@ -49,5 +49,7 @@ namespace Gremlin.Net.UnitTest.Process.Traversal
         {
             TraversalStrategies = traversalStrategies;
         }
+
+        public override Bytecode Bytecode { get; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
index 31b512a373..d50c82e303 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
@@ -26,11 +26,13 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Numerics;
+using System.Threading;
 using System.Threading.Tasks;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Structure;
 using Gremlin.Net.Structure.IO.GraphBinary;
 using Xunit;
+using Barrier = Gremlin.Net.Process.Traversal.Barrier;
 using Path = Gremlin.Net.Structure.Path;
 
 namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
@@ -76,7 +78,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
             var writer = CreateGraphBinaryWriter();
             var serializationStream = new MemoryStream();
             
-            await writer.WriteValueAsync(value, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(value, serializationStream);
 
             var serBytes = serializationStream.ToArray();
             Assert.Equal(expected, serBytes);
@@ -270,9 +272,9 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
             var reader = CreateGraphBinaryReader();
             var serializationStream = new MemoryStream();
             
-            await writer.WriteValueAsync(expected, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = await reader.ReadValueAsync<HashSet<string>>(serializationStream, false);
+            var actual = await reader.ReadNonNullableValueAsync<HashSet<string>>(serializationStream);
             
             Assert.Equal(expected, actual);
             Assert.Equal(expected.GetType(), actual.GetType());
@@ -349,9 +351,9 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
             var reader = CreateGraphBinaryReader();
             var serializationStream = new MemoryStream();
             
-            await writer.WriteValueAsync(expected, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = await reader.ReadValueAsync<Dictionary<string, int>>(serializationStream, false);
+            var actual = await reader.ReadNonNullableValueAsync<Dictionary<string, int>>(serializationStream);
             
             Assert.Equal(expected, actual);
             Assert.Equal(expected.GetType(), actual.GetType());
@@ -379,7 +381,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
             var writer = CreateGraphBinaryWriter();
             var serializationStream = new MemoryStream();
 
-            await writer.WriteValueAsync(toSerialize, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(toSerialize, serializationStream);
 
             var expected = new byte[]
                 {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
@@ -402,13 +404,12 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
         }
         
         [Fact]
-        public async Task TestVertexWithNullLabel()
+        public async Task WriteNonNullableValueShouldThrowForNullValue()
         {
-            var expected = new Vertex(123, null);
             var writer = CreateGraphBinaryWriter();
             var serializationStream = new MemoryStream();
-            
-            await Assert.ThrowsAsync<IOException>(() => writer.WriteAsync(expected, serializationStream));
+
+            await Assert.ThrowsAsync<IOException>(() => writer.WriteNonNullableValueAsync(null, serializationStream));
         }
         
         [Fact]
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs
index 49248080b1..6145f6d23b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs
@@ -40,26 +40,38 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary.Types.Sample
         {
             // Write {custom type info}, {value_flag} and {value}
             await stream.WriteAsync(_typeInfoBytes, cancellationToken).ConfigureAwait(false);
-            await WriteValueAsync(value, stream, writer, true, cancellationToken);
+            await WriteNullableValueAsync(value, stream, writer, cancellationToken);
         }
 
-        public override async Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        public override async Task WriteNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
-                if (!nullable)
-                {
-                    throw new IOException("Unexpected null value when nullable is false");
-                }
-
                 await writer.WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
                 return;
             }
 
-            if (nullable)
+            await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
+
+            var samplePerson = (SamplePerson)value;
+            var name = samplePerson.Name;
+            
+            // value_length = name_byte_length + name_bytes + long
+            await stream.WriteIntAsync(4 + Encoding.UTF8.GetBytes(name).Length + 8, cancellationToken)
+                .ConfigureAwait(false);
+
+            await writer.WriteNonNullableValueAsync(name, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(samplePerson.BirthDate, stream, cancellationToken)
+                .ConfigureAwait(false);
+        }
+        
+        public override async Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
+            CancellationToken cancellationToken = default)
+        {
+            if (value == null)
             {
-                await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
+                throw new IOException("Unexpected null value when nullable is false");
             }
 
             var samplePerson = (SamplePerson)value;
@@ -69,8 +81,8 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary.Types.Sample
             await stream.WriteIntAsync(4 + Encoding.UTF8.GetBytes(name).Length + 8, cancellationToken)
                 .ConfigureAwait(false);
 
-            await writer.WriteValueAsync(name, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(samplePerson.BirthDate, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(name, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(samplePerson.BirthDate, stream, cancellationToken)
                 .ConfigureAwait(false);
         }
 
@@ -84,19 +96,16 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary.Types.Sample
                 throw new IOException("{custom_type_info} should not be provided for this custom type");
             }
 
-            return await ReadValueAsync(stream, reader, true, cancellationToken).ConfigureAwait(false);
+            return await ReadNullableValueAsync(stream, reader, cancellationToken).ConfigureAwait(false);
         }
 
-        public override async Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        public override async Task<object> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            if (nullable)
+            var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
+            if ((valueFlag & 1) == 1)
             {
-                var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
-                if ((valueFlag & 1) == 1)
-                {
-                    return null;
-                }
+                return null;
             }
             
             // Read the byte length of the value bytes
@@ -112,10 +121,35 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary.Types.Sample
                 throw new IOException($"Not enough readable bytes: {valueLength} (expected: {stream.Length})");
             }
 
-            var name = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var name = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
+                .ConfigureAwait(false);
+            var birthDate =
+                (DateTimeOffset)await reader.ReadNonNullableValueAsync<DateTimeOffset>(stream, cancellationToken)
+                    .ConfigureAwait(false);
+
+            return new SamplePerson(name, birthDate);
+        }
+        
+        public override async Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default)
+        {
+            // Read the byte length of the value bytes
+            var valueLength = await stream.ReadIntAsync(cancellationToken).ConfigureAwait(false);
+
+            if (valueLength <= 0)
+            {
+                throw new IOException($"Unexpected value length: {valueLength}");
+            }
+
+            if (valueLength > stream.Length)
+            {
+                throw new IOException($"Not enough readable bytes: {valueLength} (expected: {stream.Length})");
+            }
+
+            var name = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var birthDate =
-                (DateTimeOffset)await reader.ReadValueAsync<DateTimeOffset>(stream, false, cancellationToken)
+                (DateTimeOffset)await reader.ReadNonNullableValueAsync<DateTimeOffset>(stream, cancellationToken)
                     .ConfigureAwait(false);
 
             return new SamplePerson(name, birthDate);
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs
index 09ea73475a..908e03f90d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs
@@ -47,11 +47,27 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary.Types.Sample
             
             Assert.Equal(expected, actual);
         }
+        
+        [Fact]
+        public async Task ReadNullableValueAndWriteNullableValueShouldBeSymmetric()
+        {
+            var expected = new SamplePerson("Olivia", new DateTimeOffset(2010, 4, 29, 5, 30, 3, TimeSpan.FromHours(1)));
+            var registry = TypeSerializerRegistry.Build()
+                .AddCustomType(typeof(SamplePerson), new SamplePersonSerializer()).Create();
+            var writer = CreateGraphBinaryWriter(registry);
+            var reader = CreateGraphBinaryReader(registry);
+            var serializationStream = new MemoryStream();
 
-        [Theory]
-        [InlineData(false)]
-        [InlineData(true)]
-        public async Task ReadValueAndWriteValueShouldBeSymmetric(bool nullable)
+            await writer.WriteNullableValueAsync(expected, serializationStream).ConfigureAwait(false);
+            serializationStream.Position = 0;
+            var actual = (SamplePerson)await reader.ReadNullableValueAsync<SamplePerson>(serializationStream)
+                .ConfigureAwait(false);
+            
+            Assert.Equal(expected, actual);
+        }
+
+        [Fact]
+        public async Task ReadNonNullableValueAndWriteNonNullableValueShouldBeSymmetric()
         {
             var expected = new SamplePerson("Olivia", new DateTimeOffset(2010, 4, 29, 5, 30, 3, TimeSpan.FromHours(1)));
             var registry = TypeSerializerRegistry.Build()
@@ -60,9 +76,9 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary.Types.Sample
             var reader = CreateGraphBinaryReader(registry);
             var serializationStream = new MemoryStream();
 
-            await writer.WriteValueAsync(expected, serializationStream, nullable).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(expected, serializationStream).ConfigureAwait(false);
             serializationStream.Position = 0;
-            var actual = (SamplePerson)await reader.ReadValueAsync<SamplePerson>(serializationStream, nullable)
+            var actual = (SamplePerson)await reader.ReadNonNullableValueAsync<SamplePerson>(serializationStream)
                 .ConfigureAwait(false);
             
             Assert.Equal(expected, actual);
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
index ad78334029..da6a6a75e8 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/BytecodeGraphSONSerializerTests.cs
@@ -163,5 +163,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
             Bytecode = bytecode;
             IsAnonymous = true;
         }
+
+        public override Bytecode Bytecode { get; }
     }
 }
\ No newline at end of file