diesel-rs/diesel · error · syn::Error
this derive can only be used on non-unit structs
Error message
this derive can only be used on non-unit structs
What it means
Diesel struct-mapping derives require named or tuple structs with at least one field; unit structs carry no fields and thus cannot map to table columns. `from_item` in model.rs raises this error at the mixed_site span when the input is not a struct with fields (or is a unit struct while `allow_unit_structs` is false).
Solutions
- Give the struct at least one field corresponding to a table column.
- Remove the diesel derive if the type is only a marker.
- If mapping a single column, use a tuple/newtype struct with a field, not a unit struct.
Example fix
// before #[derive(Queryable)] struct UserId; // after #[derive(Queryable)] struct UserId(#[diesel(column_name = id)] i32);
Defensive patterns
Strategy: validation
Validate before calling
// Diesel struct derives need a struct with fields:
// struct Good { id: i32 } // OK
// struct Good(i32); // OK (tuple fields need column_name)
// struct Unit; // FAILS
// let _ = std::mem::size_of::<T>(); // companion check: unit structs compile but derive-fail Prevention
- Do not put diesel derives on marker/phantom unit structs.
- After refactoring a struct to unit form, remove its diesel derives.
- Use enums only with the enum-specific diesel derives, not struct-mapping derives.
When it happens
Trigger: Deriving `Queryable`, `Identifiable`, `Associations`, `Insertable`, etc. on a unit struct like `struct User;`, or on an enum/union where the derive doesn't accept it.
Common situations: Marker/phantom types accidentally carrying diesel derives; refactoring a struct to `struct X;` leaving derives behind; applying a struct derive to an enum.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- expected a integer literal expression, but got something…
- no `#[diesel(sql_type = ...)]` attribute provided
- all fields of tuple structs must be annotated with…
- `embed` and `treat_none_as_default_value` are mutually…
- `#[diesel(embed)]` cannot be combined with…
AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07).
Data as JSON: /api/errors/ba41a4b6739e87fb.
Report an issue: GitHub.
Appendix: source
Thrown at diesel_derives/src/model.rs:61
item: &DeriveInput,
allow_unit_structs: bool,
allow_multiple_table: bool,
) -> Result<Self> {
let DeriveInput {
data, ident, attrs, ..
} = item;
let fields = match *data {
Data::Struct(DataStruct {
fields: Fields::Named(FieldsNamed { ref named, .. }),
..
}) => Some(named),
Data::Struct(DataStruct {
fields: Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }),
..
}) => Some(unnamed),
_ if !allow_unit_structs => {
return Err(syn::Error::new(
proc_macro2::Span::mixed_site(),
"this derive can only be used on non-unit structs",
));
}
_ => None,
};
let mut table_names = vec![];
let mut primary_key_names = vec![Ident::new("id", Span::mixed_site())];
let mut treat_none_as_default_value = None;
let mut treat_none_as_null = None;
let mut belongs_to = vec![];
let mut sql_types = vec![];
let mut aggregate = false;
let mut not_sized = false;
let mut enum_type = false;
let mut foreign_derive = false;
let mut mysql_type = None;View on GitHub (pinned to 6fa6ed01b2)