JamesNK/Newtonsoft.Json · error · InvalidOperationException
Enum name '{0}' already exists on enum '{1}'.
Error message
Enum name '{0}' already exists on enum '{1}'. What it means
InitializeValuesAndNames (EnumUtils.cs:52-92) builds the EnumInfo by computing each member's resolved name (from [EnumMember(Value=...)] then the NamingStrategy). It checks for duplicates at EnumUtils.cs:75-78: if an already-seen resolved name collides with the current one, it throws InvalidOperationException naming both the duplicate name and the enum.
Source
Thrown at Src/Newtonsoft.Json/Utilities/EnumUtils.cs:77
for (int i = 0; i < names.Length; i++)
{
string name = names[i];
FieldInfo f = enumType.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static)!;
values[i] = ToUInt64(f.GetValue(null)!);
string resolvedName;
#if HAVE_DATA_CONTRACTS
string? specifiedName = f.GetCustomAttributes(typeof(EnumMemberAttribute), true)
.Cast<EnumMemberAttribute>()
.Select(a => a.Value)
.SingleOrDefault();
hasSpecifiedName = specifiedName != null;
resolvedName = specifiedName ?? name;
if (Array.IndexOf(resolvedNames, resolvedName, 0, i) != -1)
{
throw new InvalidOperationException("Enum name '{0}' already exists on enum '{1}'.".FormatWith(CultureInfo.InvariantCulture, resolvedName, enumType.Name));
}
#else
resolvedName = name;
hasSpecifiedName = false;
#endif
resolvedNames[i] = key.Value2 != null
? key.Value2.GetPropertyName(resolvedName, hasSpecifiedName)
: resolvedName;
}
bool isFlags = enumType.IsDefined(typeof(FlagsAttribute), false);
return new EnumInfo(isFlags, values, names, resolvedNames);
}
public static IList<T> GetFlagsValues<T>(T value) where T : struct
{View on GitHub (pinned to 4f73e74372)
Solutions
- Make every [EnumMember(Value=...)] distinct across the enum.
- Adjust the NamingStrategy (or member names) so resolved names stay unique.
- Rename the colliding enum members so they differ even after transformation.
- Audit enum members after changing the serializer's NamingStrategy.
Example fix
// before [EnumMember(Value = "active")] Active, [EnumMember(Value = "active")] ActiveNow, // collision -> throws // after [EnumMember(Value = "active")] Active, [EnumMember(Value = "active_now")] ActiveNow,
Defensive patterns
Strategy: validation
Validate before calling
// Detect duplicate resolved enum names before serialization at startup.
static void CheckEnumNames(Type enumType, Newtonsoft.Json.Serialization.NamingStrategy? ns) {
var names = Enum.GetNames(enumType).Select(n => ns != null ? ns.GetPropertyName(n, false) : n);
if (names.GroupBy(n => n).Any(g => g.Count() > 1)) throw new InvalidOperationException("Duplicate enum resolved names.");
} Type guard
static bool EnumNamesUnique(Type enumType, Newtonsoft.Json.Serialization.NamingStrategy? ns) => Enum.GetNames(enumType).Select(n => ns != null ? ns.GetPropertyName(n, false) : n).Distinct().Count() == Enum.GetNames(enumType).Length;
Try / catch
try { JsonConvert.SerializeObject(obj, settings); } catch (InvalidOperationException ex) when (ex.Message.Contains("already exists on enum")) { /* fix [EnumMember]/naming strategy */ } Prevention
- Keep [EnumMember(Value=...)] values distinct across the enum.
- Re-audit enum members after changing NamingStrategy.
- Add a startup test that asserts enum resolved names are unique under your strategy.
When it happens
Trigger: Two enum members resolve to the same serialized name — either via identical [EnumMember(Value="x")] attributes, or because a NamingStrategy (camelCase, snake_case) maps distinct member names onto the same string.
Common situations: Refactoring/renaming enum members that then collide under a naming strategy; copy-paste of [EnumMember(Value=...)] values; switching NamingStrategy (e.g. to SnakeCaseNamingStrategy) causing previously-unique names to collapse.
Related errors
- Enum type {0} is not a set of flags.
- Integer string '{0}' is not allowed.
- Requested value '{0}' was not found.
- Unexpected merge array handling when merging JSON.
- value
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/b132b0ead08da0c3.
Report an issue: GitHub.