MonoGame/MonoGame · error · ArgumentException

Vertex channel with name {name} already exists

Error message

Vertex channel with name {name} already exists

What it means

Thrown by VertexChannelCollection.Insert<ElementType> when a channel with the specified name already exists. The collection enforces unique channel names — IndexOf(name) returns >= 0 for duplicates. This applies to both Insert(index, name, data) and Add(name, data) (which calls Insert at the end). Channel names follow encoded conventions (e.g., 'Normal0', 'TextureCoordinate0', 'Color1').

Source

Thrown at MonoGame.Framework.Content.Pipeline/Graphics/VertexChannelCollection.cs:229

            return _channels.IndexOf(item);
        }

        /// <summary>
        /// Inserts a new vertex channel at the specified position.
        /// </summary>
        /// <typeparam name="ElementType">Type of the new channel.</typeparam>
        /// <param name="index">Index for channel insertion.</param>
        /// <param name="name">Name of the new channel.</param>
        /// <param name="channelData">The new channel.</param>
        /// <returns>The inserted vertex channel.</returns>
        public VertexChannel<ElementType> Insert<ElementType>(int index, string name, IEnumerable<ElementType>? channelData)
        {
            if ((index < 0) || (index > _channels.Count))
                throw new ArgumentOutOfRangeException(nameof(index));
            ArgumentException.ThrowIfNullOrEmpty(name);
            // Don't insert a channel with the same name
            if (IndexOf(name) >= 0)
                throw new ArgumentException("Vertex channel with name " + name + " already exists");
            var channel = new VertexChannel<ElementType>(name);
            if (channelData != null)
            {
                // Insert the values from the enumerable into the channel
                channel.InsertRange(0, channelData);
                // Make sure we have the right number of vertices
                if (channel.Count != _vertexContent.VertexCount)
                    throw new ArgumentOutOfRangeException(nameof(channelData));
            }
            else
            {
                // Insert enough default values to fill the channel
                channel.InsertRange(0, new ElementType[_vertexContent.VertexCount]);
            }
            _channels.Insert(index, channel);
            return channel;
        }

View on GitHub (pinned to 1d71bbd0ff)

Solutions

  1. Check Channels.Contains(name) or IndexOf(name) < 0 before calling Add or Insert
  2. Remove the existing channel first with Channels.Remove(name) if you intend to replace it
  3. Use ConvertChannelContent<T> to transform an existing channel in-place rather than adding a new one
  4. Generate unique names using VertexChannelNames encoding helpers (e.g., VertexChannelNames.Normal(1))

Example fix

// before
channels.Add(VertexChannelNames.Normal(0), normals); // throws if 'Normal0' exists

// after
if (channels.Contains(VertexChannelNames.Normal(0)))
    channels.Remove(VertexChannelNames.Normal(0));
channels.Add(VertexChannelNames.Normal(0), normals);
Defensive patterns

Strategy: validation

Validate before calling

// Check for existing channel name before inserting
if (vertexContent.Channels.Contains(name))
    vertexContent.Channels.Remove(name); // or skip insertion
vertexContent.Channels.Add<T>(name, data);

Try / catch

try { channels.Add<T>(name, data); }
catch (ArgumentException ex) when (ex.Message.Contains("already exists"))
{ /* remove existing channel and retry, or skip */ }

Prevention

When it happens

Trigger: Calling Channels.Add('Normal', data) when a channel named 'Normal' (or 'Normal0') already exists. Also triggered when inserting a channel whose name collides with an existing one after vertex data has been modified.

Common situations: Importing a model that already has normals and then adding normals again in a custom processor; calling Add multiple times in a loop without checking Contains(name); name encoding mismatches where 'Normal' and 'Normal0' are treated as different by user code but the collection sees a collision.

Related errors


AI-assisted analysis of MonoGame/MonoGame@1d71bbd0ff (2026-08-13). Data as JSON: /api/errors/1eea6ce391854c14. Report an issue: GitHub.