{"record":{"id":"929f471e06f87630","repo":"transact-rs/sqlx","slug":"cannot-use-both-try-from-and-json-nullable","errorCode":null,"errorMessage":"Cannot use both try from and json nullable","messagePattern":"Cannot use both try from and json nullable","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sqlx-macros-core/src/derives/row.rs","lineNumber":180,"sourceCode":"\n                    parse_quote!(\n                        __row.try_get::<::sqlx::types::Json<_>, _>(#id_s)\n                            .and_then(|v| {\n                                <#ty as ::std::convert::TryFrom::<#try_from>>::try_from(v.0)\n                                    .map_err(|e| {\n                                        // Triggers a lint warning if `TryFrom::Err = Infallible`\n                                        #[allow(unreachable_code)]\n                                        ::sqlx::Error::ColumnDecode {\n                                            index: #id_s.to_string(),\n                                            source: sqlx::__spec_error!(e),\n                                        }\n                                    })\n                            })\n                    )\n                },\n                // Try from + Json nullable\n                (false, Some(_), Some(JsonAttribute::Nullable)) => {\n                    panic!(\"Cannot use both try from and json nullable\")\n                },\n                // Json\n                (false, None, Some(JsonAttribute::NonNullable)) => {\n                    predicates\n                        .push(parse_quote!(::sqlx::types::Json<#ty>: ::sqlx::decode::Decode<#lifetime, R::Database>));\n                    predicates.push(parse_quote!(::sqlx::types::Json<#ty>: ::sqlx::types::Type<R::Database>));\n\n                    parse_quote!(__row.try_get::<::sqlx::types::Json<_>, _>(#id_s).map(|x| x.0))\n                },\n                (false, None, Some(JsonAttribute::Nullable)) => {\n                    predicates\n                        .push(parse_quote!(::core::option::Option<::sqlx::types::Json<#ty>>: ::sqlx::decode::Decode<#lifetime, R::Database>));\n                    predicates.push(parse_quote!(::core::option::Option<::sqlx::types::Json<#ty>>: ::sqlx::types::Type<R::Database>));\n\n                    parse_quote!(__row.try_get::<::core::option::Option<::sqlx::types::Json<_>>, _>(#id_s).map(|x| x.and_then(|y| y.0)))\n                },\n            };\n","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/transact-rs/sqlx/blob/03af8bcc5711a1935580a54bea249c219a0c217d/sqlx-macros-core/src/derives/row.rs#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Drop the `json(nullable)` attribute and keep `try_from` if the column is a plain (possibly nullable) SQL value convertible via TryFrom.","Drop `try_from` and keep `#[sqlx(json)]` if the column truly stores JSON; handle nullability with `Option<T>` as the field type.","Split into two fields or use a custom FromRow implementation if both conversion steps are genuinely needed."],"exampleFix":"// before\n#[derive(sqlx::FromRow)]\nstruct Row {\n    #[sqlx(try_from = \"String\")]\n    #[sqlx(json(nullable))]\n    payload: Payload,\n}\n\n// after (json only, Option for nullability)\n#[derive(sqlx::FromRow)]\nstruct Row {\n    #[sqlx(json)]\n    payload: Option<Payload>,\n}","handlingStrategy":"validation","validationCode":"// Detect conflicting try_from + json attributes before building\nrg -n '#\\[sqlx\\(try_from' -A2 src/ | rg '#\\[sqlx\\(json'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use Option<T> field types for nullability instead of json(nullable) combined with try_from","Keep try_from for scalar conversions and json for JSON columns, never both","Review derive attribute diffs when refactoring struct fields"],"tags":["compile-time","proc-macro","derive-fromrow","sqlx"],"backgroundTag":"conflicting-derive-attributes","analyzedSha":"03af8bcc5711a1935580a54bea249c219a0c217d","analyzedAt":"2026-09-03T15:01:28.752Z","contentChangedAt":"2026-09-03T15:01:28.752Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}