diesel-rs/diesel · warning

#[ ] attribute form is deprecated

Error message

#[{ident}] attribute form is deprecated

What it means

This is a deprecation warning emitted by diesel's attribute parser during a `#[derive(Queryable, Identifiable, ...)]` expansion. Diesel used to accept bare attributes like `#[table_name = "users"]` / `#[primary_key(id)]` directly on the derived struct; these now must be namespaced as `#[diesel(table_name = "users")]`. The `warn!` macro wraps the identifier's span and message so the compiler points at the exact offending attribute. It does not fail the build — the old form still works until removed.

Solutions

  1. Prefix every diesel attribute with `diesel::`, e.g. change `#[table_name = "users"]` to `#[diesel(table_name = "users")]`
  2. Do the same for related attributes: `#[diesel(primary_key(id))]`, `#[diesel(belongs_to(User))]`, `#[diesel(column_name = x)]`
  3. Read the `= help:` note attached to the warning — it states the exact replacement form for that attribute
  4. Run `cargo fix` or manually sweep the crate with `cargo build 2>&1 | grep deprecated` to find all occurrences

Example fix

// before
#[derive(Queryable, Identifiable)]
#[table_name = "users"]
#[primary_key(id)]
pub struct User { pub id: i32, pub name: String }
// after
#[derive(Queryable, Identifiable)]
#[diesel(table_name = users)]
#[diesel(primary_key(id))]
pub struct User { pub id: i32, pub name: String }
Defensive patterns

Strategy: validation

Validate before calling

// grep-style check a team can run in CI to catch old attribute forms before building
grep -rnE '#\[(table_name|primary_key|belongs_to|column_name|foreign_key|select_expression)[ (=]' src/ \
  && echo 'Deprecated diesel attribute form found — namespace with #[diesel(...)]' && exit 1 || true

Prevention

When it happens

Trigger: Deriving diesel traits on a struct that still uses the old un-namespaced attribute syntax, e.g. `#[table_name = "posts"]`, `#[primary_key(id)]`, `#[belongs_to(User, foreign_key = "user_id")]`, `#[column_name = "x"]` without the `#[diesel(...)]` prefix. Occurs during `cargo build`/`cargo check` whenever the parser hits such an attribute.

Common situations: Upgrading diesel from 1.x/early 2.0 to 2.x where attribute namespacing became required by convention; code generated by older tutorials or books; copy-pasted derive structs from older projects; lint-clean CI builds surfacing the warnings after a dependency bump.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07). Data as JSON: /api/errors/15693d3d9405aa0b. Report an issue: GitHub.

Appendix: source

Thrown at diesel_attribute_parser/src/deprecated/mod.rs:54

#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
mod impl_deprecated {
    use super::{ParseDeprecated, ParseStream, Result};
    use crate::deprecated::belongs_to::parse_belongs_to;
    use crate::deprecated::changeset_options::parse_changeset_options;
    use crate::deprecated::postgres_type::parse_postgres_type;
    use crate::deprecated::primary_key::parse_primary_key;
    use crate::deprecated::utils::parse_eq_and_lit_str;
    use crate::notes::{
        COLUMN_NAME_NOTE, MYSQL_TYPE_NOTE, SQL_TYPE_NOTE, SQLITE_TYPE_NOTE, TABLE_NAME_NOTE,
    };
    use crate::parsers::{MysqlType, PostgresType, SqliteType};
    use crate::{FieldAttr, StructAttr};
    use proc_macro2::Span;
    use syn::Ident;

    macro_rules! warn {
        ($ident: expr_2021, $help: expr_2021) => {
            warn(
                $ident.span(),
                &format!("#[{}] attribute form is deprecated", $ident),
                $help,
            );
        };
    }

    impl ParseDeprecated for StructAttr {
        fn parse_deprecated(input: ParseStream) -> Result<Option<Self>> {
            let name: Ident = input.parse()?;
            let name_str = name.to_string();

            match &*name_str {
                "table_name" => {
                    let lit_str = parse_eq_and_lit_str(name.clone(), input, TABLE_NAME_NOTE)?;
                    warn!(
                        name,
                        &format!("use `#[diesel(table_name = {})]` instead", lit_str.value())

View on GitHub (pinned to 6fa6ed01b2)