reactiveui/refit · error · JsonException

Enum {typeof(TEnum)} does not use an unsigned backing type.

Error message

Enum {typeof(TEnum)} does not use an unsigned backing type.

What it means

Thrown by EnumHelpers.ToUInt64 when converting an enum value to an unsigned 64-bit number but the enum's underlying type is signed (sbyte/short/int/long). The switch only covers unsigned TypeCodes; a signed enum falls to the default arm. It is the mirror of error 37.

Source

Thrown at src/Refit/EnumHelpers.cs:164

                TypeCode.SByte => Unsafe.As<TEnum, sbyte>(ref value),
                TypeCode.Int16 => Unsafe.As<TEnum, short>(ref value),
                TypeCode.Int32 => Unsafe.As<TEnum, int>(ref value),
                TypeCode.Int64 => Unsafe.As<TEnum, long>(ref value),
                _ => throw new JsonException($"Enum {typeof(TEnum)} does not use a signed backing type.")
            };

        /// <summary>Converts an enum value to an unsigned 64-bit number without boxing.</summary>
        /// <param name="value">The enum value.</param>
        /// <returns>The unsigned numeric value.</returns>
        /// <exception cref="JsonException"><typeparamref name="TEnum"/> is backed by a signed type, so it has no unsigned representation.</exception>
        internal static ulong ToUInt64(TEnum value) =>
            _underlyingTypeCode switch
            {
                TypeCode.Byte => Unsafe.As<TEnum, byte>(ref value),
                TypeCode.UInt16 => Unsafe.As<TEnum, ushort>(ref value),
                TypeCode.UInt32 => Unsafe.As<TEnum, uint>(ref value),
                TypeCode.UInt64 => Unsafe.As<TEnum, ulong>(ref value),
                _ => throw new JsonException($"Enum {typeof(TEnum)} does not use an unsigned backing type.")
            };

        /// <summary>Converts a numeric backing value to the enum type without boxing.</summary>
        /// <typeparam name="TUnderlying">The enum backing value type.</typeparam>
        /// <param name="value">The numeric backing value.</param>
        /// <returns>The enum value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static TEnum ToEnum<TUnderlying>(TUnderlying value)
            where TUnderlying : struct =>
            Unsafe.As<TUnderlying, TEnum>(ref value);
    }
}

View on GitHub (pinned to b455f65ecc)

Solutions

  1. Do not call ToUInt64 on a signed-backed enum — use ToInt64, or check EnumHelpers.IsUnsignedBackingType first.
  2. If it appears without custom EnumHelpers usage, file a Refit bug including the enum's declaration and underlying type.
  3. If an unsigned numeric form is required for a signed enum, convert via ToInt64 then cast, rather than forcing ToUInt64.

Example fix

// before — calling the unsigned helper on a signed (int) enum
public enum Flags { A, B } // backed by int
ulong v = EnumHelpers.Info<Flags>.ToUInt64(flags); // throws

// after — use the matching signed helper
long v = EnumHelpers.Info<Flags>.ToInt64(flags);
Defensive patterns

Strategy: validation

Validate before calling

// Only call ToUInt64 for unsigned-backed enums.
static ulong SafeToUInt64<TEnum>(TEnum value) where TEnum : struct, Enum =>
    EnumHelpers.Info<TEnum>.IsUnsignedBackingType(EnumHelpers.Info<TEnum>.UnderlyingTypeCode)
        ? EnumHelpers.Info<TEnum>.ToUInt64(value)
        : throw new InvalidOperationException("Enum is signed; use ToInt64.");

Prevention

When it happens

Trigger: ToUInt64 is invoked for an enum whose underlying type is signed (the default int-backed enum, for example). This is an internal helper; the serialization path is supposed to call ToUInt64 only for unsigned-backed enums, so reaching the throw indicates the signedness check was bypassed.

Common situations: Unreachable through ordinary Refit use. Could appear only if custom code calls EnumHelpers.Info<TEnum>.ToUInt64 on a signed-backed enum directly, or as an internal Refit bug.

Related errors


AI-assisted analysis of reactiveui/refit@b455f65ecc (2026-08-13). Data as JSON: /api/errors/e2db3905b0299793. Report an issue: GitHub.