Skip to content

[API Proposal]: Add transport error code to QuicException #87262

@wfurt

Description

@wfurt

Background and motivation

Related to #72666. Quic RFC (https://www.rfc-editor.org/rfc/rfc9000.html#name-transport-error-codes) defines set of error codes and we probably should surface them in cases when QuicConnection fails for one of them.

We already have ProtocolError to cover some cases when peer sends invalid data and it feels like there are also cases when the transport fail for other reasons. The proposal is to remove specific ProtocolError as Quic is still in Preview and replace it it with more generic TransportError.

We already have ApplicationErorrCode in QuicException so the proposal is to add also TransportErrorCode

API Proposal

namespace System.Net.Quic
{
    public enum QuicError
    {
        // existing members omitted

-       /// <summary>
-       /// A QUIC protocol error was encountered.
-       /// </summary>
-       ProtocolError,
+       /// <summary>
+       /// Operation failed because peer transport error occurred.  
+       /// </summary>
+       TransportError,
  }
  public class QuicException
  {
        public System.Net.Quic.QuicError QuicError { get { throw null; } }
        public long? ApplicationErrorCode { get { throw null; } }
+.      public long? TransportErrorCode { get { throw null; }}
  }
}

API Usage

  try {
    QuicConnection connection = await QuicConnection.ConnectAsync();
  }
  catch (QuicExeption ex)
  {
        log($"{ex.Message} Application error {ex.ApplicationErrorCode} transport error {ex.TransportErrorCode}");
  }

the transport errors are generally unrecoverable e.g. we do not expect separate code branches based on specific value.

Alternative Designs

namespace System.Net.Quic
{

  public class QuicException
  {
         public System.Net.Quic.QuicError QuicError { get { throw null; } }
-        public long? ApplicationErrorCode { get { throw null; } }
+.       public long? ErrorCode { get { throw null; }}
  }
}

We can unify the error code and the value would have meaning based on QuicError value. We generally felt this may be confusing and easy to make mistake and misinterpret the value.

Since the error codes are applicable only ins some cases it may not make sense to drag nullable fields in al instances.
We can subtype

namespace System.Net.Quic
{

  public class QuicTransportException: QuicException
  {
         public System.Net.Quic.QuicError QuicError { get { throw null; } }
+.       public long TransportErrorCode { get { throw null; }}
  }
}

We also talk about making the TransportErrorCode strongly typed e.g. creating enum for it. But it is not clear how stable Quic protocol is and we would need to keep up. Also RFC defines some ranges and that may be hard to map to enum. Current plan is to surface the reason in some more friendly way in text when we know it.

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Net.Quicbreaking-changeIssue or PR that represents a breaking API or functional change over a prerelease.needs-breaking-change-doc-createdBreaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions