dotnet/wpf · error · InvalidOperationException
SR.Format(SR.PathParametersIndexOutOfRange, index…
Error message
SR.Format(SR.PathParametersIndexOutOfRange, index, PathParameters.Count)
What it means
ResolvePropertyName throws this InvalidOperationException when the path string references a parameter index that does not exist in PathParameters. Property names written as '(n)' index into the PathParameters collection; if index < 0 or index >= PathParameters.Count and throwOnError is true, resolution cannot proceed and the path is invalid.
Solutions
- Add one accessor to PathParameters for every '(n)' reference in the path string, in order
- Fix the numeric index inside the path string so it is within [0, PathParameters.Count)
- Replace the '(n)' indexed syntax with literal property names if accessors are not needed
- Validate the path string and PathParameters.Count before constructing/using the PropertyPath
Example fix
// before
var path = new PropertyPath("(2).Value"); // only 2 accessors added
path.PathParameters.Add(typeof(A).GetProperty("X"));
path.PathParameters.Add(typeof(B).GetProperty("Y"));
// after
var path = new PropertyPath("(1).Value");
path.PathParameters.Add(typeof(A).GetProperty("X"));
path.PathParameters.Add(typeof(B).GetProperty("Y")); Defensive patterns
Strategy: validation
Validate before calling
// pathString is the raw path; count '(n)' references and compare
int maxIdx = System.Text.RegularExpressions.Regex.Matches(pathString, "\\((\\d+)\\)")
.Select(m => int.Parse(m.Groups[1].Value)).DefaultIfEmpty(-1).Max();
bool inRange = maxIdx < path.PathParameters.Count; Type guard
bool IndexInRange(int i, System.Collections.ICollection c) => i >= 0 && i < c.Count;
Try / catch
try { path.ResolvePropertyName(index, item, context, throwOnError: true); }
catch (InvalidOperationException ex) when (ex.Message.Contains("out of range")) { /* fix index or add parameter */ } Prevention
- Keep a 1:1 correspondence between '(n)' references in the path string and PathParameters entries
- Log/assert PathParameters.Count when constructing indexed paths
- Use literal property names when accessors are unnecessary
When it happens
Trigger: A path string like '(5).Text' when PathParameters.Count is 3; calling new PropertyPath(pathString) with '(n)' references but never adding the corresponding accessors; negative indices from malformed path syntax.
Common situations: Copy-pasting property path strings between bindings without updating the PathParameters collection; generating paths dynamically where the accessor count depends on runtime data; typos in the numeric index inside parentheses.
Related errors
- SR.Format(SR.ParserPrefixNSProperty, nsPrefix, name)
- SR.Format(SR.PathParameterIsNull, index)
- SR.Format(SR.PropertyPathIndexWrongType…
- SR.Format(SR.PropertyPathInvalidAccessor, (accessor !=…
- SR.Format(SR.PropertyPathNoOwnerType, ownerName)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9cf2ca08d1d08b12.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/PropertyPath.cs:560
string propertyName = name;
int index;
// first see if the name is an index into the parameter list
if (IsParameterIndex(name, out index))
{
if (0 <= index && index < PathParameters.Count)
{
object accessor = PathParameters[index];
// always throw if the accessor isn't valid - this error cannot
// be corrected later on.
if (!IsValidAccessor(accessor))
throw new InvalidOperationException(SR.Format(SR.PropertyPathInvalidAccessor,
(accessor != null) ? accessor.GetType().FullName : "null"));
return accessor;
}
else if (throwOnError)
throw new InvalidOperationException(SR.Format(SR.PathParametersIndexOutOfRange, index, PathParameters.Count));
else return null;
}
// handle attached-property syntax: (TypeName.PropertyName)
if (IsPropertyReference(name))
{
name = name.Substring(1, name.Length-2);
int lastIndex = name.LastIndexOf('.');
if (lastIndex >= 0)
{
// attached property - get the owner type
propertyName = name.Substring(lastIndex + 1).Trim();
string ownerName = name.Substring(0, lastIndex).Trim();
ownerType = GetTypeFromName(ownerName, context);
if (ownerType == null && throwOnError)
throw new InvalidOperationException(SR.Format(SR.PropertyPathNoOwnerType, ownerName));
}View on GitHub (pinned to 81131a70a4)