{"record":{"id":"1376060a2b7f88cc","repo":"stride3d/stride","slug":"asset-returned-by-createassets-has-no-location-use","errorCode":null,"errorMessage":"Asset returned by CreateAssets has no location. Use GenerateLocation to generate the location for each asset.","messagePattern":"Asset returned by CreateAssets has no location\\. Use GenerateLocation to generate the location for each asset\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.Assets.Presentation/Templates/AssetTemplateGenerator.cs","lineNumber":44,"sourceCode":"            parameters.Validate();\n            return PrepareAssetCreation(parameters);\n        }\n\n        public sealed override bool Run(AssetTemplateGeneratorParameters parameters)\n        {\n            var assets = CreateAssets(parameters)?.ToList();\n            if (assets == null)\n            {\n                parameters.Logger.Error(\"No asset created by the asset factory.\");\n                return false;\n            }\n\n            // Step one: add assets to package with proper unique name\n            var newAssets = new Dictionary<AssetId, AssetItem>();\n            foreach (var asset in assets)\n            {\n                if (string.IsNullOrEmpty(asset.Location))\n                    throw new InvalidOperationException($\"Asset returned by {nameof(CreateAssets)} has no location. Use {nameof(GenerateLocation)} to generate the location for each asset.\");\n\n                // Ensure unicity of names amongst package\n                var name = NamingHelper.ComputeNewName(asset.Location, x => parameters.Package.Assets.Find(x) != null, \"{0}_{1}\");\n                var item = new AssetItem(name, asset.Asset);\n\n                try\n                {\n                    parameters.Package.Assets.Add(item);\n                    // Ensure the dirty flag is properly set to refresh the dependency manager\n                    item.IsDirty = true;\n                }\n                catch (Exception ex)\n                {\n                    parameters.Logger.Error(\"Failed to create new asset from template.\", ex);\n                    return false;\n                }\n                newAssets.Add(item.Id, item);\n            }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.Assets.Presentation/Templates/AssetTemplateGenerator.cs#L26-L62","documentation":"AssetTemplateGenerator.Run adds each asset produced by CreateAssets to the target package and requires every AssetItem to have a non-empty Location so unique names can be computed. An asset with an empty Location indicates the generator forgot to call GenerateLocation, so Run throws InvalidOperationException.","triggerScenarios":"A custom AssetTemplateGenerator overrides CreateAssets and returns AssetItem instances constructed without a location (e.g. new AssetItem(asset) with empty string/null location) instead of using GenerateLocation(parameters).","commonSituations":"Third-party template generator implementations copied from outdated samples; refactoring CreateAssets to build AssetItems directly instead of through the base-class helper.","solutions":["In CreateAssets, wrap each created asset with GenerateLocation(parameters) before yielding the AssetItem","Ensure the generated location string is non-empty (factory created a valid asset with a default name)","Inspect your custom generator's CreateAssets override; the base generator already calls GenerateLocation, so avoid bypassing it"],"exampleFix":"// before\nyield return new AssetItem(string.Empty, asset);\n// after\nyield return new AssetItem(GenerateLocation(parameters), asset);","handlingStrategy":"validation","validationCode":"foreach (var item in CreateAssets(parameters))\n    if (string.IsNullOrEmpty(item.Location)) throw new InvalidOperationException(\"Asset item has no location\");","typeGuard":"bool HasLocation(AssetItem a) => !string.IsNullOrEmpty(a.Location);","tryCatchPattern":"try { generator.Run(parameters, assets); }\ncatch (InvalidOperationException) { // surface 'missing location' as a template-authoring bug\n}","preventionTips":["Always route asset creation through GenerateLocation(parameters) in custom generators","Add a unit test that applies every custom template and asserts non-empty locations","Never construct AssetItem directly with a hand-written location in generators"],"tags":["stride","templates","assets"],"backgroundTag":"empty-required-field","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}