stride3d/stride · error · InvalidOperationException
[{nameof(Description)}.{nameof(Description.Scope)}] must be
Error message
[{nameof(Description)}.{nameof(Description.Scope)}] must be {TemplateScope.Package} in {GetType().Name} What it means
PackageTemplateGeneratorParameters.ValidateParameters throws this InvalidOperationException when the template Description.Scope is not TemplateScope.Package while the concrete parameters type is exactly PackageTemplateGeneratorParameters. The scope recorded in the TemplateDescription must match the parameters type used, otherwise the generator would run a package-level template with the wrong assumptions; the check is skipped for derived types like AssetTemplateGeneratorParameters which enforce their own scope.
Solutions
- Set the template description's Scope property to TemplateScope.Package (or fix the .sdtpl/description file) so it matches PackageTemplateGeneratorParameters.
- If the template is really asset- or session-scoped, use AssetTemplateGeneratorParameters or SessionTemplateGeneratorParameters instead.
- Check which TemplateDescription you assigned to the Description property — it likely belongs to a different template.
Example fix
// before
var p = new PackageTemplateGeneratorParameters(baseParams, package)
{
Description = assetTemplateDescription // Scope == TemplateScope.Asset
};
p.Validate(); // throws
// after
assetTemplateDescription.Scope = TemplateScope.Package; // or use the matching description
var p = new PackageTemplateGeneratorParameters(baseParams, package)
{
Description = packageTemplateDescription // Scope == TemplateScope.Package
};
p.Validate(); Defensive patterns
Strategy: validation
Validate before calling
if (p is PackageTemplateGeneratorParameters pp && pp.Description?.Scope != TemplateScope.Package)
throw new InvalidOperationException($"Template '{pp.Description?.Id}' scope {pp.Description?.Scope} does not match PackageTemplateGeneratorParameters."); Type guard
bool ScopeMatches(PackageTemplateGeneratorParameters p) => p.Description?.Scope == TemplateScope.Package;
Try / catch
try { p.Validate(); }
catch (InvalidOperationException ex) when (ex.Message.Contains(nameof(TemplateDescription.Scope)))
{
// fix the template description Scope or pick the right parameters type
} Prevention
- Keep each template's .sdtpl description Scope value in sync with the parameters type you feed it.
- Never reuse one TemplateDescription across differently-scoped generators.
- Assert Description.Scope immediately after loading the template description.
When it happens
Trigger: Calling Validate() on a PackageTemplateGeneratorParameters instance whose Description was loaded from a template whose TemplateDescription.Scope is Session or Asset (or left at a non-Package default).
Common situations: Mixing up template description files when wiring custom generators: pointing a package generator at an asset template's .sdtpl description; a typo or refactor changing the Scope value in the template description; reusing one Description object across differently-scoped parameters.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- [{nameof(Description)}.{nameof(Description.Scope)}] must be
- [{nameof(Session)}] cannot be null in {GetType().Name}
- [{nameof(Package)}] cannot be null in {GetType().Name}
- [{nameof(Name)}] cannot be null in {GetType().Name}
- [{nameof(OutputDirectory)}] cannot be null in {GetType().Nam
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/508d45b3929bad1d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/Templates/TemplateGeneratorParameters.cs:55
public PackageTemplateGeneratorParameters(TemplateGeneratorParameters parameters, Package package)
: base(parameters)
{
Package = package;
}
/// <summary>
/// Gets or sets the package in which to execute this template
/// </summary>
/// <value>The package.</value>
public Package Package { get; set; }
protected override void ValidateParameters()
{
base.ValidateParameters();
if (Description.Scope != TemplateScope.Package && GetType() == typeof(PackageTemplateGeneratorParameters))
{
throw new InvalidOperationException($"[{nameof(Description)}.{nameof(Description.Scope)}] must be {TemplateScope.Package} in {GetType().Name}");
}
if (Package == null)
{
throw new InvalidOperationException($"[{nameof(Package)}] cannot be null in {GetType().Name}");
}
}
}
public class AssetTemplateGeneratorParameters : PackageTemplateGeneratorParameters
{
public AssetTemplateGeneratorParameters(UDirectory targetLocation, IEnumerable<UFile>? sourceFiles = null)
{
TargetLocation = targetLocation;
SourceFiles = [];
if (sourceFiles != null)
SourceFiles.AddRange(sourceFiles);
}
View on GitHub (pinned to 96fad776d2)