{"record":{"id":"3303d074b6fad3f8","repo":"bevyengine/bevy","slug":"sampler-attribute-must-have-matching-texture-attri","errorCode":null,"errorMessage":"sampler attribute must have matching texture attribute","messagePattern":"sampler attribute must have matching texture attribute","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bevy_render/macros/src/as_bind_group.rs","lineNumber":711,"sourceCode":"                    // Add the texture to the `BindlessResourceType` list in the\n                    // bindless descriptor.\n                    add_bindless_resource_type(\n                        &render_path,\n                        &mut bindless_resource_types,\n                        binding_index,\n                        bindless_resource_type,\n                    );\n                }\n\n                BindingType::Sampler => {\n                    let SamplerAttrs {\n                        sampler_binding_type,\n                        visibility,\n                        ..\n                    } = get_sampler_attrs(nested_meta_items)?;\n                    let TextureAttrs { dimension, .. } = tex_attrs\n                        .as_ref()\n                        .expect(\"sampler attribute must have matching texture attribute\");\n\n                    let visibility =\n                        visibility.hygienic_quote(&quote! { #render_path::render_resource });\n\n                    let fallback_image = get_fallback_image(&render_path, *dimension);\n\n                    let expected_samplers = match sampler_binding_type {\n                        SamplerBindingType::Filtering => {\n                            quote!( [#render_path::render_resource::TextureSampleType::Float { filterable: true }] )\n                        }\n                        SamplerBindingType::NonFiltering => quote!([\n                            #render_path::render_resource::TextureSampleType::Float { filterable: false },\n                            #render_path::render_resource::TextureSampleType::Sint,\n                            #render_path::render_resource::TextureSampleType::Uint,\n                        ]),\n                        SamplerBindingType::Comparison => {\n                            quote!( [#render_path::render_resource::TextureSampleType::Depth] )\n                        }","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_render/macros/src/as_bind_group.rs#L693-L729","documentation":"In `#[derive(AsBindGroup)]` (bevy_render's proc macro) every `#[sampler(n)]` binding must be paired with a matching `#[texture(m)]` attribute, conventionally directly above it on the same field, so the macro can derive the expected texture sample type and the fallback image. During macro expansion the code does `tex_attrs.as_ref().expect(\"sampler attribute must have matching texture attribute\")`, so a sampler without a texture aborts compilation with this panic.","triggerScenarios":"A field of an AsBindGroup struct annotated with only `#[sampler(N)]` (no `#[texture(M)]` on the same field), or a texture attribute that was deleted/moved during refactoring while the sampler attribute stayed behind.","commonSituations":"Writing a new custom material and forgetting the texture attribute; trimming a material down to a sampler-only field; copy-pasting binding attributes between fields and breaking the texture/sampler pairing.","solutions":["Add a matching `#[texture(M, dimension = \"2D\")]` attribute directly above the `#[sampler(N)]` on the same field","If you truly need no texture, remove the `#[sampler]` attribute and provide the binding manually (custom AsBindGroup impl or a storage binding)","Verify binding indices stay unique per binding type after the fix"],"exampleFix":"// before\n#[derive(Asset, AsBindGroup)]\nstruct MyMaterial {\n    #[uniform(0)]\n    color: Vec4,\n    #[sampler(1)]\n    tex: Option<Handle<Image>>,\n}\n\n// after\n#[derive(Asset, AsBindGroup)]\nstruct MyMaterial {\n    #[uniform(0)]\n    color: Vec4,\n    #[texture(2, dimension = \"2D\")]\n    #[sampler(1)]\n    tex: Option<Handle<Image>>,\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write #[texture(M)] and #[sampler(N)] as a pair on the same field","When deleting a texture field, delete both attributes together","Copy working attribute blocks from bevy's material examples when adding new bindings"],"tags":["bevy","as-bind-group","proc-macro","material","compile-time"],"backgroundTag":"derive-macro-attribute-mismatch","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}