stride3d/stride · error · ArgumentException
This parameter must be a formattable string containing
Error message
This parameter must be a formattable string containing '{0}' and '{1}' tokens What it means
NamingHelper.ComputeNewName generates names using a pattern that must contain both {0} (base name) and {1} (counter) placeholders. If the supplied namePattern is missing either token, the generated names could not include the required parts, so an ArgumentException naming the namePattern parameter is thrown.
Solutions
- Fix the pattern to include both tokens, e.g. "{0} {1}" or "{0}-{1}".
- Pass null to use DefaultNamePattern instead of a custom one.
- Validate the pattern with Contains checks before calling ComputeNewName.
- Catch ArgumentException and fall back to the default pattern.
Example fix
// before
NamingHelper.ComputeNewName(names, contains, "newName-")
// after
NamingHelper.ComputeNewName(names, contains, "{0}-{1}") Defensive patterns
Strategy: validation
Validate before calling
if (pattern == null || (!pattern.Contains("{0}") || !pattern.Contains("{1}"))) pattern = null; // fall back to default
NamingHelper.ComputeNewName(existingNames, contains, pattern); Type guard
bool IsValidNamePattern(string? p) => p == null || (p.Contains("{0}") && p.Contains("{1}")); Try / catch
try { newName = NamingHelper.ComputeNewName(names, contains, pattern); }
catch (ArgumentException ex) when (ex.ParamName == "namePattern") { newName = NamingHelper.ComputeNewName(names, contains, null); } Prevention
- Always include {0} and {1} tokens in custom patterns
- Pass null to use DefaultNamePattern
- Unit-test custom patterns before shipping
When it happens
Trigger: Passing a custom namePattern string to ComputeNewName that lacks "{0}" or "{1}" (e.g. "{name}-{count}" or a plain string).
Common situations: Hand-written rename patterns copied from other tools that use different placeholder syntax; localization or formatting changes that removed a token; defaulting code that passes empty/blank patterns.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Value type for root objects are not supported
- The index must be an int.
- The index must be an int.
- ArgumentNullException
- ArgumentException
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/6f274038cb81406a.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Design/NamingHelper.cs:119
/// <summary>
/// Generate a name for a new object that is guaranteed to be unique for the provided "contains predicate". To generate such name, a base name and a pattern for variations must be provided.
/// </summary>
/// <param name="baseName">The base name used to generate the new name. If the name is available in the collection, it will be returned as-is. Otherwise, a name following the given pattern will be returned.</param>
/// <param name="containsDelegate">The delegate used to determine if the asset is already existing</param>
/// <param name="namePattern">The pattern used to generate the new name, when the base name is unavailable. This pattern must contains the token '{0}' that will be replaced by the base name, and the token '{1}' that will be replaced by the smallest numerical value that can generate an available name, starting from 2. If null, <see cref="DefaultNamePattern"/> will be used instead.</param>
/// <returns><see cref="baseName"/> if the "contains predicate" returns false. Otherwise, a string formatted with <see cref="namePattern"/>, using <see cref="baseName"/> as token '{0}' and the smallest numerical value that can generate an available name, starting from 2</returns>
public static string ComputeNewName(string baseName, ContainsLocationDelegate containsDelegate, string? namePattern = null)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(baseName);
ArgumentNullException.ThrowIfNull(containsDelegate);
#else
if (baseName is null) throw new ArgumentNullException(nameof(baseName));
if (containsDelegate is null) throw new ArgumentNullException(nameof(containsDelegate));
#endif
namePattern ??= DefaultNamePattern;
if (!namePattern.Contains("{0}") || !namePattern.Contains("{1}")) throw new ArgumentException("This parameter must be a formattable string containing '{0}' and '{1}' tokens", nameof(namePattern));
// First check if the base name itself is ok
if (!containsDelegate(baseName))
return baseName;
// Initialize counter
var counter = 1;
// Checks whether baseName already 'implements' the namePattern
var match = Regex.Match(baseName, $"^{Regex.Escape(namePattern).Replace(@"\{0}", "(.*)").Replace(@"\{1}", @"(\d+)")}$");
if (match.Success && match.Groups.Count >= 3)
{
// if so, extract the base name and the current counter
var intValue = int.Parse(match.Groups[2].Value);
// Ensure there is no leading 0 messing around
if (intValue.ToString() == match.Groups[2].Value)
{
baseName = match.Groups[1].Value;
counter = intValue;View on GitHub (pinned to 96fad776d2)