diesel-rs/diesel · error

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

Error message

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

What it means

The `AsChangeset` derive in diesel rejects a struct field annotated with both `#[diesel(embed)]` and `#[diesel(serialize_as)]`. `embed` inlines a nested struct's fields, while `serialize_as` converts the field to a different Rust type for serialization; the generated code cannot combine both transformations, so the derive emits a compile error pointing at the field's `serialize_as` attribute span.

Solutions

  1. Remove `#[diesel(serialize_as)]` from the embedded field and apply `serialize_as` on the inner struct's own fields instead.
  2. Remove `#[diesel(embed)]` if the field genuinely needs type conversion during updates.
  3. Split the struct: keep the embedded value object separate from the converted field.

Example fix

// before
#[derive(AsChangeset)]
struct UserChangeset {
    #[diesel(embed)]
    #[diesel(serialize_as = "String")]
    name: MyNameWrapper,
}

// after
#[derive(AsChangeset)]
struct UserChangeset {
    #[diesel(embed)]
    name: NameFields,
}
Defensive patterns

Strategy: validation

Validate before calling

// Attribute audit before compiling
fn validate_field_attrs(attrs: &[&str]) -> Result<(), String> {
    let has_embed = attrs.iter().any(|a| a.contains("embed"));
    let has_serialize_as = attrs.iter().any(|a| a.contains("serialize_as"));
    if has_embed && has_serialize_as {
        return Err("a field cannot use both #[diesel(embed)] and #[diesel(serialize_as)]".into());
    }
    Ok(())
}

Prevention

When it happens

Trigger: Deriving `AsChangeset` (usually via `#[derive(AsChangeset)]` or `AsChangeset` pulled in through `ActiveModel`-style patterns) on a struct where the same field carries both `#[diesel(embed)]` and `#[diesel(serialize_as = "...")]`.

Common situations: Developers copy a field's `serialize_as` from a pre-embed version of the struct, then add `embed` to inline a nested struct without removing the old attribute; refactoring structs to nest value objects while keeping old conversion annotations.

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


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

Appendix: source

Thrown at diesel_derives/src/as_changeset.rs:109

                direct_field_assign.push(field_changeset_expr_serialize_as(
                    field,
                    table_name,
                    ty,
                    treat_none_as_null,
                )?);
                field_ty_bounds.push(generate_field_bound(
                    field,
                    table_name,
                    Some(ty),
                    None,
                    &mut field_ty_bounds_guard,
                    treat_none_as_null,
                )?);

                generate_borrowed_changeset = false; // as soon as we hit one field with #[diesel(serialize_as)] there is no point in generating the impl of AsChangeset for borrowed structs
            }
            (Some(AttributeSpanWrapper { attribute_span, .. }), true) => {
                return Err(syn::Error::new(
                    *attribute_span,
                    "`#[diesel(embed)]` cannot be combined with `#[diesel(serialize_as)]`",
                ));
            }
            (None, true) => {
                direct_field_ty.push(field_changeset_ty_embed(field, None));
                direct_field_assign.push(field_changeset_expr_embed(field, None));
                ref_field_ty.push(field_changeset_ty_embed(field, Some(quote!(&'update))));
                ref_field_assign.push(field_changeset_expr_embed(field, Some(quote!(&))));
            }
            (None, false) => {
                direct_field_ty.push(field_changeset_ty(
                    field,
                    table_name,
                    None,
                    treat_none_as_null,
                )?);
                direct_field_assign.push(field_changeset_expr(

View on GitHub (pinned to 6fa6ed01b2)