bevyengine/bevy · error · syn::Error
`type_path` already set to {}
Error message
`type_path` already set to {} What it means
`#[reflect(type_path = <bool>)]` toggles automatic `TypePath` generation by the Reflect derive. Like `from_reflect`, it can only be set once: `parse_type_path` (crates/bevy_reflect/derive/src/container_attributes.rs:462) errors with "`type_path` already set to {previous}" on a second, conflicting value. The `TypePath` derive/`#[reflect(TypePath)]` provenance forces `true` via the mapper override, so mixing it with `type_path = false` triggers the error.
Source
Thrown at crates/bevy_reflect/derive/src/container_attributes.rs:481
&mut self,
input: ParseStream,
trait_: ReflectTraitToImpl,
) -> syn::Result<()> {
let pair = input.parse::<MetaNameValue>()?;
let extracted_bool = extract_bool(&pair.value, |lit| {
// Override `lit` if this is a `FromReflect` derive.
// This typically means a user is opting out of the default implementation
// from the `Reflect` derive and using the `FromReflect` derive directly instead.
if trait_ == ReflectTraitToImpl::TypePath {
LitBool::new(true, Span::call_site())
} else {
lit.clone()
}
})?;
if let Some(existing) = &self.type_path_attrs.auto_derive {
if existing.value() != extracted_bool.value() {
return Err(syn::Error::new(
extracted_bool.span(),
format!("`{TYPE_PATH_ATTR}` already set to {}", existing.value()),
));
}
} else {
self.type_path_attrs.auto_derive = Some(extracted_bool);
}
Ok(())
}
/// Returns true if the given reflected trait name (i.e. `ReflectDefault` for `Default`)
/// is registered for this type.
pub fn contains(&self, name: &str) -> bool {
self.type_data
.iter()
.any(|data| data.reflect_path().is_ident(name))
}View on GitHub (pinned to 396ca72708)
Solutions
- Choose one source of truth: the `TypePath` derive (true) or `#[reflect(type_path = false)]`, never both
- If you disabled it to supply a custom path, make sure no `TypePath` derive remains on the type
- Consolidate reflect attributes into a single list
Example fix
// before: "`type_path` already set to false"
#[derive(Reflect, TypePath)]
#[reflect(type_path = false)]
struct Foo;
// after: keep the explicit setting, drop the conflicting derive
#[derive(Reflect)]
#[reflect(type_path = false)]
impl std::fmt::Debug for Foo { /* ... */ } Defensive patterns
Strategy: validation
Validate before calling
null
Prevention
- Don't mix #[derive(TypePath)] (or #[reflect(TypePath)]) with #[reflect(type_path = false)]
- Set each boolean toggle in exactly one place
- Use `cargo expand` (or rust-analyzer expand) to inspect the final attribute set when unsure
When it happens
Trigger: `#[derive(Reflect, TypePath)]` plus `#[reflect(type_path = false)]`, or two `#[reflect(...)]` lists giving different bools for `type_path`. Same-value repetition is allowed.
Common situations: Disabling generated TypePath (e.g. for a custom `#[type_path = "..."]` setup or generic workaround) while another derive or attribute still enables it; attribute lists duplicated during refactors.
Related errors
- `#[type_path = "..."]` must be a string literal
- conflicting type data registration
- `from_reflect` already set to {}
- Expected a boolean value
- `#[reflect("...")]` must use parentheses `(` and `)`
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/a6b4627f18bf422a.
Report an issue: GitHub.