{"record":{"id":"c45616836c3fcda7","repo":"SeaQL/sea-orm","slug":"failed-to-get-small-integer-c45616","errorCode":null,"errorMessage":"Failed to get small integer","messagePattern":"Failed to get small integer","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sea-orm-sync/src/driver/sqlx_postgres.rs","lineNumber":443,"sourceCode":"                            Value::Bool(row.try_get(c.ordinal()).expect(\"Failed to get boolean\"))\n                        }\n                        #[cfg(feature = \"postgres-array\")]\n                        \"BOOL[]\" => Value::Array(\n                            sea_query::ArrayType::Bool,\n                            row.try_get::<Option<Vec<bool>>, _>(c.ordinal())\n                                .expect(\"Failed to get boolean array\")\n                                .map(|vals| {\n                                    Box::new(\n                                        vals.into_iter()\n                                            .map(|val| Value::Bool(Some(val)))\n                                            .collect(),\n                                    )\n                                }),\n                        ),\n\n                        \"\\\"CHAR\\\"\" => Value::TinyInt(\n                            row.try_get(c.ordinal())\n                                .expect(\"Failed to get small integer\"),\n                        ),\n                        #[cfg(feature = \"postgres-array\")]\n                        \"\\\"CHAR\\\"[]\" => Value::Array(\n                            sea_query::ArrayType::TinyInt,\n                            row.try_get::<Option<Vec<i8>>, _>(c.ordinal())\n                                .expect(\"Failed to get small integer array\")\n                                .map(|vals: Vec<i8>| {\n                                    Box::new(\n                                        vals.into_iter()\n                                            .map(|val| Value::TinyInt(Some(val)))\n                                            .collect(),\n                                    )\n                                }),\n                        ),\n\n                        \"SMALLINT\" | \"SMALLSERIAL\" | \"INT2\" => Value::SmallInt(\n                            row.try_get(c.ordinal())\n                                .expect(\"Failed to get small integer\"),","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/SeaQL/sea-orm/blob/e29bcd1b417c41a553b386fe94511d7c64a1c8ec/sea-orm-sync/src/driver/sqlx_postgres.rs#L425-L461","documentation":"Panic while converting a Postgres row to ProxyRow: a column reporting type name `\"CHAR\"` (the internal 1-byte `\"char\"` type) is decoded with `row.try_get::<i8>(ordinal).expect(\"Failed to get small integer\")`. `try_get` fails when the value is NULL (scalar target cannot be NULL) or the value is not decodable as `i8` — e.g. the column is actually `character(1)` (char/varchar), which sqlx reports differently but which developers often confuse with `\"CHAR\"`.","triggerScenarios":"Reading a nullable `\"char\"` column through ProxyRow so `try_get::<i8>` hits `UnexpectedNullError`; or querying a `char(1)`/`bpchar` column whose type-info match lands on the `\"CHAR\"` branch but whose Rust decode target i8 does not fit; or a DOMAIN over `\"char\"`.","commonSituations":"Reading Postgres catalog columns (many system catalogs use nullable `\"char\"` pseudo-booleans like `proisagg`-style flags); confusing SQL `CHAR(1)` with Postgres internal `\"char\"`; schema where a single-char column was created as varchar but matched by an alias.","solutions":["Decode as Option: `row.try_get::<Option<i8>, _>(c.ordinal())` and map to `Value::TinyInt(opt)` so NULL does not panic.","If the column is really `character(1)`, decode as `Option<String>`/`char` and convert, or fix the type-name match to target the correct branch.","COALESCE the column in SQL (`COALESCE(col, 0)`) if NULL should be 0.","ALTER the column to SET NOT NULL when the model guarantees a value.","Confirm the actual type with `SELECT pg_typeof(col)`; adjust the match arm or the query cast (`col::\"char\"`)."],"exampleFix":"// before (panics on NULL)\n\"\\\"CHAR\\\"\" => Value::TinyInt(row.try_get(c.ordinal()).expect(\"Failed to get small integer\")),\n// after (NULL-safe)\n\"\\\"CHAR\\\"\" => Value::TinyInt(\n    row.try_get::<Option<i8>, _>(c.ordinal())\n        .expect(\"Failed to get small integer\")\n        .unwrap_or_default(),\n),","handlingStrategy":"try-catch","validationCode":"// SELECT data_type, is_nullable FROM information_schema.columns\n//   WHERE table_name = 't' AND udt_name = 'char'; -- distinguish \"char\" from bpchar\nlet type_name = col.type_info().name().to_string();\ndebug_assert_eq!(type_name, \"\\\"CHAR\\\"\", \"unexpected column type: {}\", type_name);","typeGuard":"fn as_char_i8(row: &ProxyRow, col: &str) -> Option<i8> {\n    match row.value(col) {\n        Some(Value::TinyInt(v)) => v,\n        _ => None,\n    }\n}","tryCatchPattern":"let result = std::panic::catch_unwind(|| proxy_row_get_i8(&row, \"cat_flag\"));\nmatch result {\n    Ok(v) => v,\n    Err(_) => treat_as_null_or_default(), // log actual column type for diagnosis\n}","preventionTips":["Remember \"char\" (quoted) is the 1-byte internal type; CHAR(1) is bpchar — map each to the right decode target.","Use Option<i8> for nullable catalog \"char\" columns (common in system catalogs).","COALESCE nullable \"char\" columns in SQL when a default is acceptable.","Cast DOMAINs over \"char\" to the base type in the query."],"tags":["postgres","sqlx","type-decode","null-value","panic"],"backgroundTag":"type-mismatch","analyzedSha":"e29bcd1b417c41a553b386fe94511d7c64a1c8ec","analyzedAt":"2026-09-10T11:31:52.468Z","contentChangedAt":"2026-09-10T11:31:52.468Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}