{"record":{"id":"b885660549847bf2","repo":"MonoGame/MonoGame","slug":"effectmaterialcontent-effect-or-effectmaterialcont","errorCode":null,"errorMessage":"EffectMaterialContent.Effect or EffectMaterialContent.CompiledEffect should be set for materials with a custom effect.","messagePattern":"EffectMaterialContent\\.Effect or EffectMaterialContent\\.CompiledEffect should be set for materials with a custom effect\\.","errorType":"exception","errorClass":"PipelineException","httpStatus":null,"severity":"error","filePath":"MonoGame.Framework.Content.Pipeline/Processors/MaterialProcessor.cs","lineNumber":173,"sourceCode":"                    newMaterial.Textures.Add(item.Key, item.Value);\n\n                input = newMaterial;\n            }\n\n            // Docs say that if it's a basic effect, only build the diffuse texture.\n            if (input is BasicMaterialContent basic)\n            {\n                if (basic.Textures.TryGetValue(BasicMaterialContent.TextureKey, out var texture))\n                    basic.Texture = BuildTexture(texture.Filename, texture, context);\n\n                return basic;\n            }\n\n            // Build custom effects\n            if (input is EffectMaterialContent { CompiledEffect: null } effectMaterial)\n            {\n                if (effectMaterial.Effect == null)\n                    throw new PipelineException(\"EffectMaterialContent.Effect or EffectMaterialContent.CompiledEffect should be set for materials with a custom effect.\");\n                effectMaterial.CompiledEffect = BuildEffect(effectMaterial.Effect, context);\n                // TODO: Docs say to validate OpaqueData for SetValue/SetValueTranspose\n                // Does that mean to match up with effect param names??\n            }\n\n            // Build all textures\n            var keys = new List<string>(input.Textures.Keys);\n            foreach (var key in keys)\n            {\n                var texture = input.Textures[key];\n                var builtTexture = BuildTexture(texture.Filename, texture, context);\n                input.Textures[key] = builtTexture;\n            }\n\n            return input;\n        }\n\n        /// <summary>","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/MonoGame/MonoGame/blob/1d71bbd0ff4071a03caa583aa3bc56b85924a819/MonoGame.Framework.Content.Pipeline/Processors/MaterialProcessor.cs#L155-L191","documentation":"Thrown by MaterialProcessor.Process when the input is an EffectMaterialContent with CompiledEffect set to null and Effect also set to null. An EffectMaterialContent represents a custom shader material, so at least one of Effect (source .fx reference) or CompiledEffect (pre-compiled effect reference) must be provided.","triggerScenarios":"Creating an EffectMaterialContent programmatically or via .mgcontent XML without setting either the Effect or CompiledEffect property, then passing it through the MaterialProcessor pipeline.","commonSituations":"A material XML file declares a custom effect material but omits the <Effect> or <CompiledEffect> element. Programmatically constructing an EffectMaterialContent and forgetting to assign Effect before processing. Deserialization from a malformed or incomplete material definition.","solutions":["Set effectMaterial.Effect to an ExternalReference<EffectContent> pointing to the .fx source file before processing.","Alternatively set effectMaterial.CompiledEffect if you have a pre-compiled effect.","If using an XML material definition, ensure it includes a valid <Effect> or <CompiledEffect> node."],"exampleFix":"// before\nvar mat = new EffectMaterialContent();\n// Effect and CompiledEffect both null\ncontext.BuildAsset<MaterialContent, MaterialContent>(mat, ...);\n\n// after\nvar mat = new EffectMaterialContent();\nmat.Effect = new ExternalReference<EffectContent>(\"Effects/Custom.fx\");\ncontext.BuildAsset<MaterialContent, MaterialContent>(mat, ...);","handlingStrategy":"validation","validationCode":"// Validate EffectMaterialContent before processing\nif (input is EffectMaterialContent emc && emc.CompiledEffect == null && emc.Effect == null)\n    throw new InvalidOperationException(\"EffectMaterialContent requires Effect or CompiledEffect to be set.\");","typeGuard":"// Type guard for a valid effect material\nstatic bool HasValidEffect(EffectMaterialContent emc) =>\n    emc.Effect != null || emc.CompiledEffect != null;","tryCatchPattern":"try\n{\n    context.BuildAsset<MaterialContent, MaterialContent>(material, new MaterialProcessor());\n}\ncatch (PipelineException ex) when (ex.Message.Contains(\"EffectMaterialContent\"))\n{\n    context.Logger.LogImportantMessage(\"EffectMaterialContent needs Effect or CompiledEffect set.\");\n    throw;\n}","preventionTips":["Always set Effect on EffectMaterialContent before passing to the processor.","Use factory methods that enforce required properties.","Validate material content in a pre-build step."],"tags":["material","content-pipeline","effect","validation","mgcb"],"backgroundTag":null,"analyzedSha":"1d71bbd0ff4071a03caa583aa3bc56b85924a819","analyzedAt":"2026-08-13T17:10:33.625Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}