diesel-rs/diesel · error
`embed` and `treat_none_as_default_value` are mutually…
Error message
`embed` and `treat_none_as_default_value` are mutually exclusive
What it means
In the `Insertable` derive, a field marked `#[diesel(embed)]` (splicing another table's columns in) cannot also set `treat_none_as_default_value`, since embedded fields don't map to a single column with a default. The check in derive_into_single_table rejects the combination at insertable.rs:61.
Solutions
- Remove `treat_none_as_default_value` from the embedded field (or from the struct level for that field).
- Apply `treat_none_as_default_value` only to plain `Option<T>` fields, not embedded ones.
- If you need default handling inside the embedded struct, set it within that nested type's own derive.
Example fix
// before
#[derive(Insertable)]
#[diesel(table_name = posts)]
struct NewPost {
#[diesel(embed, treat_none_as_default_value = true)]
meta: PostMeta,
}
// after
#[derive(Insertable)]
#[diesel(table_name = posts)]
struct NewPost {
#[diesel(embed)]
meta: PostMeta,
} Defensive patterns
Strategy: validation
Validate before calling
// Never combine embed with treat_none_as_default_value on one field: // #[diesel(embed)] // OK // #[diesel(embed, treat_none_as_default_value = true)] // FAILS
Prevention
- Reserve `treat_none_as_default_value` for plain Option<T> fields.
- Audit struct-level `treat_none_as_default_value` when adding embedded fields.
- Configure defaults inside the embedded type's own derive instead.
When it happens
Trigger: A struct-level or field-level `treat_none_as_default_value` attribute applied to a field that also has `#[diesel(embed)]`.
Common situations: Setting `treat_none_as_default_value` at the struct level while some fields embed nested insertables; copy-pasting option/default handling onto embedded fields.
Related errors
- `#[diesel(embed)]` cannot be combined with…
- expected a integer literal expression, but got something…
- no `#[diesel(sql_type = ...)]` attribute provided
- all fields of tuple structs must be annotated with…
- this derive can only be used on non-unit structs
AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07).
Data as JSON: /api/errors/5ef7822273ecd89b.
Report an issue: GitHub.
Appendix: source
Thrown at diesel_derives/src/insertable.rs:61
let mut ref_field_ty = Vec::with_capacity(model.fields().len());
let mut ref_field_assign = Vec::with_capacity(model.fields().len());
// Explicit trait bounds to improve error messages
let mut field_ty_bounds = Vec::with_capacity(model.fields().len());
let mut borrowed_field_ty_bounds = Vec::with_capacity(model.fields().len());
let mut field_ty_bounds_guard = HashMap::new();
let mut borrowed_field_ty_bounds_guard = HashMap::new();
for field in model.fields() {
// skip this field while generating the insertion
if field.skip_insertion() {
continue;
}
// Use field-level attr. with fallback to the struct-level one.
let treat_none_as_default_value = match &field.treat_none_as_default_value {
Some(attr) => {
if let Some(embed) = &field.embed {
return Err(syn::Error::new(
embed.attribute_span,
"`embed` and `treat_none_as_default_value` are mutually exclusive",
));
}
if !is_option_ty(&field.ty) {
return Err(syn::Error::new(
field.ty.span(),
"expected `treat_none_as_default_value` field to be of type `Option<_>`",
));
}
attr.item
}
None => treat_none_as_default_value,
};
match (field.serialize_as.as_ref(), field.embed()) {View on GitHub (pinned to 6fa6ed01b2)