FyroxEngine/Fyrox · warning
Unable to use material property
Error message
Unable to use material property {} because of mismatching types.Expected {:?} got {:?}. Fallback to shader default value. What it means
In the renderer's uniform-writing macro, a material property was found for a shader property but its `MaterialPropertyRef` variant does not match the shader-declared value type (e.g. shader expects Vector4, material supplies Float). The renderer logs the mismatch and pushes the shader's default value instead, so the object renders with fallback data rather than your material value.
Solutions
- Open the logged property name and align the material property type with the shader property's declared kind (Float, Vector2/3/4, Color, etc.)
- Fix the shader definition so the property type matches what the material assigns
- Re-save/recreate the affected material so stored property types refresh against the current shader
- If the mismatch is intentional legacy data, migrate the material (convert e.g. scalar to vector) before rendering
Example fix
// before
material.set_property("tint", 0.5); // shader expects Vector4<f32>
// after
material.set_property("tint", Vector4::new(0.5, 0.5, 0.5, 1.0)); Defensive patterns
Strategy: type-guard
Validate before calling
fn assert_property_type(material: &Material, name: &str, expected: PropertyKind) {
if let Some(p) = material.get_property(name) {
assert_eq!(p.kind(), expected, "material property '{name}' has wrong type");
}
} Type guard
fn as_vec4(p: &MaterialPropertyRef) -> Option<Vector4<f32>> {
match p {
MaterialPropertyRef::Vector4(v) => Some(*v),
_ => None,
}
} Try / catch
if let Some(prop) = material.get_property("tint") {
if !matches!(prop, MaterialPropertyRef::Vector4(_)) {
eprintln!("'tint' must be Vector4, got {prop:?}");
}
} Prevention
- Keep shader property definitions and material property assignments in sync during refactors
- Resave materials after changing shader property types
- Write unit tests that bind representative materials against each shader
- Avoid mixing scalar and vector property names across shaders
When it happens
Trigger: `write_with_material` (invoked by `write_uniforms` during rendering) encounters a material property whose Rust type/variant differs from the corresponding `ShaderProperty`'s value kind — e.g. assigning a `Color` or scalar where the shader property is declared as a vector3/vector4/array.
Common situations: Editing a material property name in code after the shader expects a different type; shader hot-reload changed a property's type while saved materials keep the old type; copy-pasting property definitions between shaders with different types; loading old scene files against updated shaders.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unable to use texture binding
- Animation: unable to set value of type
- Cast to failed!
- Graphics context is uninitialized!
- only rectangle textures can be used as render target!
AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10).
Data as JSON: /api/errors/6bcd92228e931732.
Report an issue: GitHub.
Appendix: source
Thrown at fyrox-impl/src/renderer/bundle.rs:259
getter: G,
buf: &mut UniformBuffer<T>,
) where
T: ByteStorage,
G: for<'a> Fn(&'a C, &ImmutableString) -> Option<MaterialPropertyRef<'a>>,
{
// The order of fields is strictly defined in shader, so we must iterate over shader definition
// of a structure and look for respective values in the material.
for shader_property in shader_property_group {
let material_property = getter(material_property_group, &shader_property.name);
macro_rules! push_value {
($variant:ident, $shader_value:ident) => {
if let Some(property) = material_property {
if let MaterialPropertyRef::$variant(material_value) = property {
buf.push(material_value);
} else {
buf.push($shader_value);
Log::err(format!(
"Unable to use material property {} because of mismatching types.\
Expected {:?} got {:?}. Fallback to shader default value.",
shader_property.name, shader_property, property
));
}
} else {
buf.push($shader_value);
}
};
}
macro_rules! push_slice {
($variant:ident, $shader_value:ident, $max_size:ident) => {
if let Some(property) = material_property {
if let MaterialPropertyRef::$variant(material_value) = property {
buf.push_slice_with_max_size(material_value, *$max_size);
} else {
buf.push_slice_with_max_size($shader_value, *$max_size);View on GitHub (pinned to 76c91aad8e)