transact-rs/sqlx · error

Cannot use both try from and json nullable

Error message

Cannot use both try from and json nullable

What it means

A compile-time panic in sqlx's `#[derive(FromRow)]` macro (expand_derive_from_row_struct). A field marked `#[sqlx(try_from = "T")]` was also marked with a nullable json attribute (`#[sqlx(json(nullable))]` or `#[sqlx(json)]` with nullability). try_from conversion and JSON deserialization are mutually exclusive generation strategies, so the macro aborts compilation with this panic.

Source

Thrown at sqlx-macros-core/src/derives/row.rs:180

                    parse_quote!(
                        __row.try_get::<::sqlx::types::Json<_>, _>(#id_s)
                            .and_then(|v| {
                                <#ty as ::std::convert::TryFrom::<#try_from>>::try_from(v.0)
                                    .map_err(|e| {
                                        // Triggers a lint warning if `TryFrom::Err = Infallible`
                                        #[allow(unreachable_code)]
                                        ::sqlx::Error::ColumnDecode {
                                            index: #id_s.to_string(),
                                            source: sqlx::__spec_error!(e),
                                        }
                                    })
                            })
                    )
                },
                // Try from + Json nullable
                (false, Some(_), Some(JsonAttribute::Nullable)) => {
                    panic!("Cannot use both try from and json nullable")
                },
                // Json
                (false, None, Some(JsonAttribute::NonNullable)) => {
                    predicates
                        .push(parse_quote!(::sqlx::types::Json<#ty>: ::sqlx::decode::Decode<#lifetime, R::Database>));
                    predicates.push(parse_quote!(::sqlx::types::Json<#ty>: ::sqlx::types::Type<R::Database>));

                    parse_quote!(__row.try_get::<::sqlx::types::Json<_>, _>(#id_s).map(|x| x.0))
                },
                (false, None, Some(JsonAttribute::Nullable)) => {
                    predicates
                        .push(parse_quote!(::core::option::Option<::sqlx::types::Json<#ty>>: ::sqlx::decode::Decode<#lifetime, R::Database>));
                    predicates.push(parse_quote!(::core::option::Option<::sqlx::types::Json<#ty>>: ::sqlx::types::Type<R::Database>));

                    parse_quote!(__row.try_get::<::core::option::Option<::sqlx::types::Json<_>>, _>(#id_s).map(|x| x.and_then(|y| y.0)))
                },
            };

View on GitHub (pinned to 03af8bcc57)

Solutions

  1. Drop the `json(nullable)` attribute and keep `try_from` if the column is a plain (possibly nullable) SQL value convertible via TryFrom.
  2. Drop `try_from` and keep `#[sqlx(json)]` if the column truly stores JSON; handle nullability with `Option<T>` as the field type.
  3. Split into two fields or use a custom FromRow implementation if both conversion steps are genuinely needed.

Example fix

// before
#[derive(sqlx::FromRow)]
struct Row {
    #[sqlx(try_from = "String")]
    #[sqlx(json(nullable))]
    payload: Payload,
}

// after (json only, Option for nullability)
#[derive(sqlx::FromRow)]
struct Row {
    #[sqlx(json)]
    payload: Option<Payload>,
}
Defensive patterns

Strategy: validation

Validate before calling

// Detect conflicting try_from + json attributes before building
rg -n '#\[sqlx\(try_from' -A2 src/ | rg '#\[sqlx\(json'

Prevention

When it happens

Trigger: Deriving FromRow with a field like `#[sqlx(try_from = "i64")] #[sqlx(json(nullable))] value: Value`. Any macro expansion for that struct (query_as!, FromRow derive) hits the `(false, Some(_), Some(JsonAttribute::Nullable))` match arm and panics.

Common situations: Combining a numeric try_from conversion with a nullable JSON column after a schema change; merging attribute sets when refactoring field types; following outdated examples that mix the two attributes.

Related errors


AI-assisted analysis of transact-rs/sqlx@03af8bcc57 (2026-09-03). Data as JSON: /api/errors/929f471e06f87630. Report an issue: GitHub.