{"record":{"id":"6f274038cb81406a","repo":"stride3d/stride","slug":"this-parameter-must-be-a-formattable-string-containing-0-and","errorCode":null,"errorMessage":"This parameter must be a formattable string containing '{0}' and '{1}' tokens","messagePattern":"This parameter must be a formattable string containing '(.+?)' and '(.+?)' tokens","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Design/NamingHelper.cs","lineNumber":119,"sourceCode":"\n    /// <summary>\n    /// 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.\n    /// </summary>\n    /// <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>\n    /// <param name=\"containsDelegate\">The delegate used to determine if the asset is already existing</param>\n    /// <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>\n    /// <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>\n    public static string ComputeNewName(string baseName, ContainsLocationDelegate containsDelegate, string? namePattern = null)\n    {\n#if NET6_0_OR_GREATER\n        ArgumentNullException.ThrowIfNull(baseName);\n        ArgumentNullException.ThrowIfNull(containsDelegate);\n#else\n        if (baseName is null) throw new ArgumentNullException(nameof(baseName));\n        if (containsDelegate is null) throw new ArgumentNullException(nameof(containsDelegate));\n#endif\n        namePattern ??= DefaultNamePattern;\n        if (!namePattern.Contains(\"{0}\") || !namePattern.Contains(\"{1}\")) throw new ArgumentException(\"This parameter must be a formattable string containing '{0}' and '{1}' tokens\", nameof(namePattern));\n\n        // First check if the base name itself is ok\n        if (!containsDelegate(baseName))\n            return baseName;\n\n        // Initialize counter\n        var counter = 1;\n        // Checks whether baseName already 'implements' the namePattern\n        var match = Regex.Match(baseName, $\"^{Regex.Escape(namePattern).Replace(@\"\\{0}\", \"(.*)\").Replace(@\"\\{1}\", @\"(\\d+)\")}$\");\n        if (match.Success && match.Groups.Count >= 3)\n        {\n            // if so, extract the base name and the current counter\n            var intValue = int.Parse(match.Groups[2].Value);\n            // Ensure there is no leading 0 messing around\n            if (intValue.ToString() == match.Groups[2].Value)\n            {\n                baseName = match.Groups[1].Value;\n                counter = intValue;","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Design/NamingHelper.cs#L101-L137","documentation":"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.","triggerScenarios":"Passing a custom namePattern string to ComputeNewName that lacks \"{0}\" or \"{1}\" (e.g. \"{name}-{count}\" or a plain string).","commonSituations":"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.","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."],"exampleFix":"// before\nNamingHelper.ComputeNewName(names, contains, \"newName-\")\n// after\nNamingHelper.ComputeNewName(names, contains, \"{0}-{1}\")","handlingStrategy":"validation","validationCode":"if (pattern == null || (!pattern.Contains(\"{0}\") || !pattern.Contains(\"{1}\"))) pattern = null; // fall back to default\nNamingHelper.ComputeNewName(existingNames, contains, pattern);","typeGuard":"bool IsValidNamePattern(string? p) => p == null || (p.Contains(\"{0}\") && p.Contains(\"{1}\"));","tryCatchPattern":"try { newName = NamingHelper.ComputeNewName(names, contains, pattern); }\ncatch (ArgumentException ex) when (ex.ParamName == \"namePattern\") { newName = NamingHelper.ComputeNewName(names, contains, null); }","preventionTips":["Always include {0} and {1} tokens in custom patterns","Pass null to use DefaultNamePattern","Unit-test custom patterns before shipping"],"tags":["csharp","argument","formatting","naming"],"backgroundTag":"invalid-argument-format","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}