JamesNK/Newtonsoft.Json · error · ArgumentOutOfRangeException
Unexpected token when writing BSON: {0}
Error message
Unexpected token when writing BSON: {0} What it means
Thrown by BsonBinaryWriter.WriteValue's default case when it encounters a BsonToken whose Type is not one of the handled BsonType values (Object, Array, Integer, Long, Number, String, Boolean, Null, Undefined, Date, Binary, Oid, Regex). It is an ArgumentOutOfRangeException indicating the BSON writer received a token it does not know how to serialize to binary. Because BsonWriter constructs these tokens internally from public Write* calls, this normally signals an internal/unsupported value path rather than a typical user mistake.
Source
Thrown at Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs:191
break;
case BsonType.Oid:
{
BsonValue value = (BsonValue)t;
byte[] data = (byte[])value.Value;
_writer.Write(data);
}
break;
case BsonType.Regex:
{
BsonRegex value = (BsonRegex)t;
WriteString((string)value.Pattern.Value, value.Pattern.ByteCount, null);
WriteString((string)value.Options.Value, value.Options.ByteCount, null);
}
break;
default:
throw new ArgumentOutOfRangeException(nameof(t), "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
}
}
private void WriteString(string s, int byteCount, int? calculatedlengthPrefix)
{
if (calculatedlengthPrefix != null)
{
_writer.Write(calculatedlengthPrefix.GetValueOrDefault());
}
WriteUtf8Bytes(s, byteCount);
_writer.Write((byte)0);
}
public void WriteUtf8Bytes(string s, int byteCount)
{
if (s != null)View on GitHub (pinned to 4f73e74372)
Solutions
- Inspect the exception message: the {0} placeholder is filled with the offending BsonType; remove or convert the value producing that token type.
- Add a custom JsonConverter/BsonConverter for the CLR type that triggered the unsupported token so it serializes as a supported BSON primitive (string, bytes, integer).
- If you are manually constructing BsonToken trees, ensure every leaf uses only supported BsonType values.
- Migrate from the obsolete in-box BSON classes to the dedicated Newtonsoft.Json.Bson NuGet package.
Example fix
// before: Guid property serializes to an unsupported token new BsonWriter(stream); serializer.Serialize(bsonWriter, modelWithGuid); // after: convert Guid to a 16-byte binary value before BSON serialization var settings = new JsonSerializerSettings(); settings.Converters.Add(new GuidToBinaryConverter()); // writes Guid as BsonType.Binary
Defensive patterns
Strategy: validation
Validate before calling
// Before serializing, ensure every leaf value maps to a supported BSON primitive.
static bool IsBsonSupported(object value) =>
value == null
|| value is int || value is long || value is double || value is decimal
|| value is bool || value is string || value is byte[]
|| value is DateTime || value is DateTimeOffset
|| value is Newtonsoft.Json.Bson.BsonObjectId;
if (!graph.All(IsBsonSupported)) throw new InvalidOperationException("unsupported BSON type"); Type guard
static bool IsSupportedBsonType(Newtonsoft.Json.Bson.BsonType t) =>
t == Newtonsoft.Json.Bson.BsonType.Object
|| t == Newtonsoft.Json.Bson.BsonType.Array
|| t == Newtonsoft.Json.Bson.BsonType.Integer
|| t == Newtonsoft.Json.Bson.BsonType.Long
|| t == Newtonsoft.Json.Bson.BsonType.Number
|| t == Newtonsoft.Json.Bson.BsonType.String
|| t == Newtonsoft.Json.Bson.BsonType.Boolean
|| t == Newtonsoft.Json.Bson.BsonType.Null
|| t == Newtonsoft.Json.Bson.BsonType.Undefined
|| t == Newtonsoft.Json.Bson.BsonType.Date
|| t == Newtonsoft.Json.Bson.BsonType.Binary
|| t == Newtonsoft.Json.Bson.BsonType.Oid
|| t == Newtonsoft.Json.Bson.BsonType.Regex; Try / catch
try { serializer.Serialize(bsonWriter, obj); }
catch (ArgumentOutOfRangeException ex) when (ex.Message.Contains("Unexpected token when writing BSON"))
{
// log the offending BsonType, convert the offending value, or fall back to JSON
throw new InvalidOperationException("Unsupported BSON token type", ex);
} Prevention
- Register custom converters for CLR types BSON does not natively support (Guid, decimal, custom structs).
- Avoid hand-building BsonToken trees; let BsonWriter derive tokens from your object graph.
- Migrate to the dedicated Newtonsoft.Json.Bson package which supersedes the obsolete in-box types.
When it happens
Trigger: Calling BsonWriter methods that produce an unsupported combination, e.g. writing a value whose runtime type cannot be mapped to a known BsonType, or directly feeding a hand-constructed BsonToken tree (BsonWriter.WriteValue with a BsonObject/BsonArray tree containing an exotic token) into the writer. Also reachable when serializing an object graph that yields a token type the BSON writer never expected (e.g. a Guid that is not wrapped as Oid/Binary).
Common situations: Using the obsolete Newtonsoft BSON support on a data model with types BSON does not natively represent (e.g. Guid without a converter, complex nested values). Migrating from the in-box BSON to the separate Newtonsoft.Json.Bson package and hitting a behavior gap. Manually building BsonToken trees in tests.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unexpected BsonType value: {0}
- An ObjectId must be 12 bytes
- Unable to read beyond the end of the stream.
- Unexpected value type when writing binary: {0}
- Expected Bytes but got {0}.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/11feca3e8e909544.
Report an issue: GitHub.