JamesNK/Newtonsoft.Json · error · ArgumentException

An ObjectId must be 12 bytes

Error message

An ObjectId must be 12 bytes

What it means

Thrown by the BsonObjectId constructor when the supplied byte array is not exactly 12 bytes long. A MongoDB ObjectId is defined as a fixed 12-byte value (4-byte timestamp, 5-byte random, 3-byte counter), so any other length is invalid. This is an ArgumentException from BsonObjectId.cs:54.

Source

Thrown at Src/Newtonsoft.Json/Bson/BsonObjectId.cs:54

    [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")]
    public class BsonObjectId
    {
        /// <summary>
        /// Gets or sets the value of the Oid.
        /// </summary>
        /// <value>The value of the Oid.</value>
        public byte[] Value { get; }

        /// <summary>
        /// Initializes a new instance of the <see cref="BsonObjectId"/> class.
        /// </summary>
        /// <param name="value">The Oid value.</param>
        public BsonObjectId(byte[] value)
        {
            ValidationUtils.ArgumentNotNull(value, nameof(value));
            if (value.Length != 12)
            {
                throw new ArgumentException("An ObjectId must be 12 bytes", nameof(value));
            }

            Value = value;
        }
    }
}

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Ensure the byte array passed to the BsonObjectId constructor is exactly 12 bytes.
  2. If you have a 24-character hex string, convert it with the correct decoder (2 hex chars -> 1 byte = 12 bytes), not Encoding.ASCII.GetBytes.
  3. If you have a Guid, do not pass it directly; map the relevant 12 bytes explicitly.
  4. Switch to the dedicated Newtonsoft.Json.Bson package which has its own ObjectId handling.

Example fix

// before: passing a hex string's ASCII bytes (24 bytes)
var oid = new BsonObjectId(Encoding.ASCII.GetBytes("507f1f77bcf86cd799439011"));

// after: decode hex to 12 bytes
byte[] bytes = Enumerable.Range(0, 24)
    .Where(i => i % 2 == 0)
    .Select(i => Convert.ToByte(hex.Substring(i, 2), 16))
    .ToArray();
var oid = new BsonObjectId(bytes);
Defensive patterns

Strategy: validation

Validate before calling

byte[] bytes = GetOidBytes();
if (bytes == null || bytes.Length != 12)
    throw new ArgumentException($"ObjectId must be 12 bytes, got {bytes?.Length ?? 0}");
var oid = new BsonObjectId(bytes);

Type guard

static bool IsValidObjectId(byte[] b) => b != null && b.Length == 12;

Try / catch

try { return new BsonObjectId(bytes); }
catch (ArgumentException ex) when (ex.Message.Contains("12 bytes"))
{
    throw new InvalidDataException($"Bad ObjectId length: {bytes?.Length}", ex);
}

Prevention

When it happens

Trigger: Calling `new BsonObjectId(bytes)` with a byte array whose Length is not 12. Commonly happens when deserializing an OID from a hex string that was converted with the wrong encoding, or when passing a 16-byte Guid or a truncated/padded value.

Common situations: Parsing a 24-char hex string but forgetting to decode it (passing the string's ASCII bytes, 24 bytes). Passing a Guid.ToByteArray() (16 bytes) directly. Reading a corrupt or partial BSON stream whose OID field is not 12 bytes. Using the obsolete in-box BsonObjectId instead of the dedicated BSON package's ObjectId type.

Related errors


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/66edb447978f8ede. Report an issue: GitHub.