bevyengine/bevy · error · syn::Error

`#[type_path = "..."]` must be a string literal

Error message

`#[type_path = "..."]` must be a string literal

What it means

`#[type_path = "..."]` overrides the module path bevy_reflect reports for a type. The value must be a string literal containing a valid Rust path without a leading `::`: `derive_data.rs` (crates/bevy_reflect/derive/src/derive_data.rs:210) matches `syn::Lit::Str` and then parses the contents with `parse_path_no_leading_colon`. Anything else — an unquoted path, a number, an expression — fails with "`#[type_path = \"...\"]` must be a string literal".

Source

Thrown at crates/bevy_reflect/derive/src/derive_data.rs:217

                Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_ATTRIBUTE_NAME) => {
                    if let MacroDelimiter::Paren(_) = meta_list.delimiter {
                        container_attributes.parse_meta_list(meta_list, provenance.trait_)?;
                    } else {
                        return Err(syn::Error::new(
                            meta_list.delimiter.span().join(),
                            format_args!(
                                "`#[{REFLECT_ATTRIBUTE_NAME}(\"...\")]` must use parentheses `(` and `)`"
                            ),
                        ));
                    }
                }
                Meta::NameValue(pair) if pair.path.is_ident(TYPE_PATH_ATTRIBUTE_NAME) => {
                    let syn::Expr::Lit(syn::ExprLit {
                        lit: syn::Lit::Str(lit),
                        ..
                    }) = &pair.value
                    else {
                        return Err(syn::Error::new(
                            pair.span(),
                            format_args!("`#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` must be a string literal"),
                        ));
                    };

                    custom_path = Some(syn::parse::Parser::parse_str(
                        parse_path_no_leading_colon,
                        &lit.value(),
                    )?);
                }
                Meta::NameValue(pair) if pair.path.is_ident(TYPE_NAME_ATTRIBUTE_NAME) => {
                    let syn::Expr::Lit(syn::ExprLit {
                        lit: syn::Lit::Str(lit),
                        ..
                    }) = &pair.value
                    else {
                        return Err(syn::Error::new(
                            pair.span(),

View on GitHub (pinned to 396ca72708)

Solutions

  1. Quote the value: `#[type_path = "my_crate::net"]`
  2. Drop any leading `::` from the path inside the string
  3. In macros, use `stringify!` or `$crate`-based `concat!` to build the string literal

Example fix

// before
#[type_path = my_crate::net]
struct Packet;

// after
#[type_path = "my_crate::net"]
struct Packet;
Defensive patterns

Strategy: validation

Validate before calling

null

Prevention

When it happens

Trigger: Writing `#[type_path = my_crate::net]` (unquoted path) or any non-string-literal value; a quoted value with a leading `::` (`"::my_crate::net"`) also fails, at the subsequent path parse.

Common situations: Renaming crates and hand-editing the attribute; macro-generated type_path attributes where the value wasn't stringified; muscle memory from `#[serde(crate = "...")]`-style values that are parsed differently.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/6a8e22feaa4c813f. Report an issue: GitHub.