diesel-rs/diesel · error · syn::Error

`#[diesel(embed)]` cannot be combined with…

Error message

`#[diesel(embed)]` cannot be combined with `#[diesel(serialize_as)]`

What it means

In the `Insertable` derive, `#[diesel(embed)]` splices a whole nested set of columns, while `#[diesel(serialize_as)]` converts a single field's type; applying both to one field is incoherent, so the derive returns this error at insertable.rs:156.

Solutions

  1. Remove one of the two attributes — they cannot coexist on the same field.
  2. If the field should be a single converted column, keep `serialize_as` and drop `embed`.
  3. If the field should splice multiple columns, keep `embed` and do the type conversion inside the embedded type's own derive.

Example fix

// before
struct NewPost {
  #[diesel(embed, serialize_as = JsonMeta)]
  meta: Meta,
}

// after
struct NewPost {
  #[diesel(embed)]
  meta: Meta, // do conversion inside Meta's own derives
}
Defensive patterns

Strategy: validation

Validate before calling

// A field is either embedded or converted via serialize_as — never both:
// #[diesel(embed)]               // splice columns
// #[diesel(serialize_as = T)]    // convert one column
// #[diesel(embed, serialize_as = T)] // FAILS

Prevention

When it happens

Trigger: A single field annotated with both `#[diesel(embed)]` and `#[diesel(serialize_as = SomeType)]`.

Common situations: Adding a serialize_as conversion to a field that was already embedded; combining wrapper-type conversion with nested insertable splicing in one attribute edit.

Related errors


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

Appendix: source

Thrown at diesel_derives/src/insertable.rs:156

                    field,
                    table_name,
                    ty,
                    treat_none_as_default_value,
                )?);

                field_ty_bounds.push(generate_field_bound(
                    field,
                    table_name,
                    ty,
                    treat_none_as_default_value,
                    None,
                    &mut field_ty_bounds_guard,
                )?);

                generate_borrowed_insert = false; // as soon as we hit one field with #[diesel(serialize_as)] there is no point in generating the impl of Insertable for borrowed structs
            }
            (Some(AttributeSpanWrapper { attribute_span, .. }), true) => {
                return Err(syn::Error::new(
                    *attribute_span,
                    "`#[diesel(embed)]` cannot be combined with `#[diesel(serialize_as)]`",
                ));
            }
        }
    }

    let field_ty_bounds = field_ty_bounds
        .into_iter()
        .filter_map(|(type_to_check, bound)| {
            filter_bounds(&field_ty_bounds_guard, type_to_check, bound)
        });
    let insert_owned = quote! {
        impl #impl_generics diesel::insertable::Insertable<#table_name::table> for #struct_name #ty_generics
        where
            #where_clause
            #(#field_ty_bounds,)*
        {

View on GitHub (pinned to 6fa6ed01b2)