{"record":{"id":"7472b90b88d037d3","repo":"transact-rs/sqlx","slug":"cannot-use-both-flatten-and-json","errorCode":null,"errorMessage":"Cannot use both flatten and json","messagePattern":"Cannot use both flatten and json","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sqlx-macros-core/src/derives/row.rs","lineNumber":134,"sourceCode":"                    predicates.push(parse_quote!(#try_from: ::sqlx::FromRow<#lifetime, R>));\n                    parse_quote!(\n                        <#try_from as ::sqlx::FromRow<#lifetime, R>>::from_row(__row)\n                            .and_then(|v| {\n                                <#ty as ::std::convert::TryFrom::<#try_from>>::try_from(v)\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                // Flatten + Json\n                (true, _, Some(_)) => {\n                    panic!(\"Cannot use both flatten and json\")\n                }\n                // Try from\n                (false, Some(try_from), None) => {\n                    predicates\n                        .push(parse_quote!(#try_from: ::sqlx::decode::Decode<#lifetime, R::Database>));\n                    predicates.push(parse_quote!(#try_from: ::sqlx::types::Type<R::Database>)); \n\n                    parse_quote!(\n                        __row.try_get(#id_s)\n                            .and_then(|v| {\n                                <#ty as ::std::convert::TryFrom::<#try_from>>::try_from(v)\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                                        }","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/transact-rs/sqlx/blob/03af8bcc5711a1935580a54bea249c219a0c217d/sqlx-macros-core/src/derives/row.rs#L116-L152","documentation":"This is a compile-time panic inside sqlx's `#[derive(FromRow)]` proc macro (expand_derive_from_row_struct). A struct field was annotated with both `#[sqlx(flatten)]` and `#[sqlx(json)]`, which are mutually exclusive codegen strategies: flatten spreads another FromRow type's columns, while json deserializes the column as JSON into the field type. The macro cannot generate code for both, so it deliberately panics to fail the build.","triggerScenarios":"Deriving FromRow on a struct where a single field carries both attributes, e.g. `#[sqlx(flatten)] #[sqlx(json)] pub meta: Meta`. Any call to `query_as!`, `query_as::<_, T>`, or `FromRow::from_row` for that struct triggers macro expansion and the panic.","commonSituations":"Refactoring a struct where one field was flattened and another was json-typed, and the attributes get copied onto the same field; merging two structs with conflicting field annotations; copy-pasting attribute lines from another field.","solutions":["Remove `#[sqlx(flatten)]` from the field if you want it deserialized from a single JSON column (keep `#[sqlx(json)]`).","Remove `#[sqlx(json)]` from the field if you want its columns merged via FromRow flatten (keep `#[sqlx(flatten)]`).","If you need both behaviors, split the data into two fields: one flattened struct field and one `#[sqlx(json)]` field."],"exampleFix":"// before\n#[derive(sqlx::FromRow)]\nstruct Row {\n    #[sqlx(flatten)]\n    #[sqlx(json)]\n    meta: Meta,\n}\n\n// after (keep json only)\n#[derive(sqlx::FromRow)]\nstruct Row {\n    #[sqlx(json)]\n    meta: Meta,\n}","handlingStrategy":"validation","validationCode":"// Compile-time: verify no field carries both attributes\ncargo check 2>&1 | grep -F 'Cannot use both flatten and json'\n// In code review, grep derives:\n// rg -n '#\\[sqlx\\(flatten\\)\\]' -A1 | rg '#\\[sqlx\\(json'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Allow only one sqlx field attribute per field by team convention","Document that flatten and json are mutually exclusive in your ORM guidelines","Run cargo check in CI so the macro panic surfaces on the first build"],"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"}