{"record":{"id":"9c63e26c7b2474bc","repo":"transact-rs/sqlx","slug":"expected-exactly-1-column-got","errorCode":null,"errorMessage":"expected exactly 1 column, got {}","messagePattern":"expected exactly 1 column, got (.+?)","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"sqlx-macros-core/src/query/output.rs","lineNumber":217,"sourceCode":"\n            #(#instantiations)*\n\n            ::std::result::Result::Ok(#out_ty { #(#ident: #var_name),* })\n        })\n    }\n}\n\npub fn quote_query_scalar<DB: DatabaseExt>(\n    input: &QueryMacroInput,\n    config: &Config,\n    warnings: &mut Warnings,\n    bind_args: &Ident,\n    describe: &Describe<DB>,\n) -> crate::Result<TokenStream> {\n    let columns = describe.columns();\n\n    if columns.len() != 1 {\n        return Err(syn::Error::new(\n            input.src_span,\n            format!(\"expected exactly 1 column, got {}\", columns.len()),\n        )\n        .into());\n    }\n\n    // attempt to parse a column override, otherwise fall back to the inferred type of the column\n    let ty = if let Ok(rust_col) = column_to_rust(describe, config, warnings, 0) {\n        rust_col.type_.to_token_stream()\n    } else if input.checked {\n        let ty = get_column_type::<DB>(config, warnings, 0, &columns[0]);\n        if describe.nullable(0).unwrap_or(true) {\n            quote! { ::std::option::Option<#ty> }\n        } else {\n            ty\n        }\n    } else {\n        quote! { _ }","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/transact-rs/sqlx/blob/03af8bcc5711a1935580a54bea249c219a0c217d/sqlx-macros-core/src/query/output.rs#L199-L235","documentation":"The `query_scalar!` family requires the query to return exactly one column, since its output type is a single value. `quote_query_scalar` checks the described result columns and fails at compile time if the count differs, including the actual count in the message.","triggerScenarios":"Using `query_scalar!`/`query_scalar_unchecked!` with SQL that returns 0 or 2+ columns — e.g. `SELECT id, name FROM users` or a query that returns no columns.","commonSituations":"Converting `query_as!` code to `query_scalar!` without trimming the select list; editing the .sql file to add a column; migrations changing a view so it now returns extra columns.","solutions":["Change the SQL to select exactly one column (e.g. `SELECT count(*) FROM ...`)","If you need multiple values, use `query_as!` with a record struct instead","If it uses a query file, fix the .sql file so it returns a single column"],"exampleFix":"// before\nlet names = query_scalar!(\"SELECT id, name FROM users\").fetch_all(&pool).await?;\n// after\nlet names = query_as!(User, \"SELECT id, name FROM users\").fetch_all(&pool).await?;\n// or for one value:\nlet count: i64 = query_scalar!(\"SELECT count(*) FROM users\").fetch_one(&pool).await?;","handlingStrategy":"validation","validationCode":"// ensure the SQL returns exactly one column before using query_scalar!\n// e.g. inspect the described query in a test:\nlet d = sqlx::describe(\"SELECT count(*) FROM users\", &pool).await?;\nassert_eq!(d.columns().len(), 1);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use query_scalar! only for single-column SELECTs","Switch to query_as! when selecting multiple columns","Review .sql files referenced by query_scalar! when schemas/views change","Let compile errors guide you — sqlx checks this at compile time"],"tags":["rust","sqlx","macros","compile-time","query-scalar"],"backgroundTag":"wrong-column-count","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"}