{"record":{"id":"f58e99b5bf7f15cc","repo":"stride3d/stride","slug":"the-buildsteps-property-cannot-be-set-to-null","errorCode":null,"errorMessage":"The BuildSteps property cannot be set to null","messagePattern":"The BuildSteps property cannot be set to null","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/Compiler/AssetCompilerResult.cs","lineNumber":30,"sourceCode":"public class AssetCompilerResult : LoggerResult\n{\n    private ListBuildStep buildSteps;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"LoggerResult\" /> class.\n    /// </summary>\n    /// <param name=\"moduleName\">Name of the module.</param>\n    public AssetCompilerResult(string? moduleName = null)\n        : base(moduleName)\n    {\n        buildSteps = new ListBuildStep();\n    }\n\n    /// <summary>\n    /// Gets or sets the build steps generated for the build engine. This can be null if <see cref=\"Logger.HasErrors\"/> is true.\n    /// </summary>\n    /// <value>The build step.</value>\n    public ListBuildStep BuildSteps { get { return buildSteps; } set { if (value == null) throw new ArgumentNullException(\"value\", @\"The BuildSteps property cannot be set to null\"); buildSteps = value; } }\n}\n","sourceCodeStart":12,"sourceCodeEnd":32,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/Compiler/AssetCompilerResult.cs#L12-L32","documentation":"AssetCompilerResult.BuildSteps is documented to be null only when the logger recorded errors; otherwise the property must always hold a ListBuildStep. The setter enforces this invariant by throwing ArgumentNullException when a caller tries to assign null while no-error results still require a valid build step list.","triggerScenarios":"Assigning null to the BuildSteps property of AssetCompilerResult in code that post-processes compiler output, e.g. result.BuildSteps = null; instead of building an empty ListBuildStep or checking Logger.HasErrors first.","commonSituations":"Custom compiler wrappers clearing steps after failure handling; refactoring that replaced a local buildSteps list with null; test code constructing AssetCompilerResult and forgetting to set a (possibly empty) step list.","solutions":["Assign a new empty ListBuildStep instead of null when there are no steps.","Only leave BuildSteps unset/null when Logger.HasErrors is true, per the documented contract.","On compilation failure, log errors via the result's Logger and leave BuildSteps at its initialized value.","Check result.Logger.HasErrors and result.BuildSteps for null before consuming steps downstream."],"exampleFix":"// before\nresult.BuildSteps = null; // after clearing steps\n// after\nif (result.Logger.HasErrors)\n{\n    // leave BuildSteps null per contract\n}\nelse\n{\n    result.BuildSteps = new ListBuildStep();\n}","handlingStrategy":"validation","validationCode":"if (result.Logger.HasErrors)\n{\n    // leave BuildSteps as-is (may be null per contract)\n}\nelse\n{\n    result.BuildSteps = buildSteps ?? new ListBuildStep();\n}","typeGuard":"static bool CanAssignBuildSteps(AssetCompilerResult result, ListBuildStep steps) => steps != null;","tryCatchPattern":"try\n{\n    result.BuildSteps = steps;\n}\ncatch (ArgumentNullException)\n{\n    result.BuildSteps = new ListBuildStep(); // never assign null\n}","preventionTips":["Never assign null to BuildSteps; use an empty ListBuildStep for no-op results.","Remember the contract: BuildSteps is null only when Logger.HasErrors is true.","Initialize ListBuildStep fields at declaration so they can never be null."],"tags":["null-argument","property-invariant","asset-compilation","build-steps"],"backgroundTag":"null-argument","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"}