icsharpcode/ILSpy · error · ReflectionNameParseException

Expected '}'

Error message

Expected '}'

What it means

ReflectionNameParseException thrown by ReadTypeParameterCountFromIdString when a bound type-argument list opened with '{' is never closed with '}' before the end of the string. The arity counter scans for the matching brace and throws at the position just past the end if it runs off the string.

Source

Thrown at ICSharpCode.Decompiler/Documentation/IdStringProvider.cs:1130

					{
						depth++;
					}
					else if (c == '}')
					{
						if (depth == 0)
						{
							pos++;
							return count;
						}
						depth--;
					}
					else if (c == ',' && depth == 0)
					{
						count++;
					}
					pos++;
				}
				throw new ReflectionNameParseException(pos, "Expected '}'");
			}

			return 0;
		}

		/// <summary>
		/// Attempts to resolve a parsed type name within a single module.
		/// The first part's Name is a dotted name like "A.B.C", and we try all possible
		/// splits between namespace and top-level type name, from right to left.
		/// For each candidate top-level type, we walk the nested types.
		/// Also checks type forwarders.
		/// </summary>
		static EntityHandle ResolveTypeInModule(List<TypeNamePart> parts, MetadataFile module)
		{
			var metadata = module.Metadata;
			string topLevelDottedName = parts[0].Name;
			string[] dotParts = topLevelDottedName.Split('.');

View on GitHub (pinned to 60c08fcb74)

Solutions

  1. Close every '{' with a matching '}' in bound type-argument syntax.
  2. Prefer the unbound arity form (e.g. "T:Foo`2") when you only need the type definition lookup.
  3. Validate brace balance before passing the ID string to FindEntity.

Example fix

// before
var e = IdStringProvider.FindEntity("T:Foo{System.Int32", context);

// after
var e = IdStringProvider.FindEntity("T:Foo{System.Int32}", context);
Defensive patterns

Strategy: try-catch

Validate before calling

static bool BracesBalanced(string s)
{
    int depth = 0;
    foreach (char c in s)
    {
        if (c == '{') depth++;
        else if (c == '}') depth--;
        if (depth < 0) return false;
    }
    return depth == 0;
}

Try / catch

try { return IdStringProvider.FindEntity(idString, context); }
catch (ReflectionNameParseException ex) { logger.Warn($"Unclosed generic args at {ex.Position}: {ex.Message}"); return null; }

Prevention

When it happens

Trigger: An ID string using bound generic syntax with an unclosed brace, e.g. "T:Foo{Bar" or "T:Foo{Bar,Baz".

Common situations: Truncating a bound-argument ID string; constructing one programmatically and forgetting the closing brace; copying a cref that was itself cut off.

Related errors


AI-assisted analysis of icsharpcode/ILSpy@60c08fcb74 (2026-08-13). Data as JSON: /api/errors/5cfc99648f8ee93f. Report an issue: GitHub.