{"record":{"id":"af6b365abdd5b70c","repo":"SeaQL/sea-orm","slug":"failed-to-get-integer-af6b36","errorCode":null,"errorMessage":"Failed to get integer","messagePattern":"Failed to get integer","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sea-orm-sync/src/driver/sqlx_postgres.rs","lineNumber":478,"sourceCode":"                            row.try_get(c.ordinal())\n                                .expect(\"Failed to get small integer\"),\n                        ),\n                        #[cfg(feature = \"postgres-array\")]\n                        \"SMALLINT[]\" | \"SMALLSERIAL[]\" | \"INT2[]\" => Value::Array(\n                            sea_query::ArrayType::SmallInt,\n                            row.try_get::<Option<Vec<i16>>, _>(c.ordinal())\n                                .expect(\"Failed to get small integer array\")\n                                .map(|vals: Vec<i16>| {\n                                    Box::new(\n                                        vals.into_iter()\n                                            .map(|val| Value::SmallInt(Some(val)))\n                                            .collect(),\n                                    )\n                                }),\n                        ),\n\n                        \"INT\" | \"SERIAL\" | \"INT4\" => {\n                            Value::Int(row.try_get(c.ordinal()).expect(\"Failed to get integer\"))\n                        }\n                        #[cfg(feature = \"postgres-array\")]\n                        \"INT[]\" | \"SERIAL[]\" | \"INT4[]\" => Value::Array(\n                            sea_query::ArrayType::Int,\n                            row.try_get::<Option<Vec<i32>>, _>(c.ordinal())\n                                .expect(\"Failed to get integer array\")\n                                .map(|vals: Vec<i32>| {\n                                    Box::new(\n                                        vals.into_iter().map(|val| Value::Int(Some(val))).collect(),\n                                    )\n                                }),\n                        ),\n\n                        \"BIGINT\" | \"BIGSERIAL\" | \"INT8\" => Value::BigInt(\n                            row.try_get(c.ordinal()).expect(\"Failed to get big integer\"),\n                        ),\n                        #[cfg(feature = \"postgres-array\")]\n                        \"BIGINT[]\" | \"BIGSERIAL[]\" | \"INT8[]\" => Value::Array(","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/SeaQL/sea-orm/blob/e29bcd1b417c41a553b386fe94511d7c64a1c8ec/sea-orm-sync/src/driver/sqlx_postgres.rs#L460-L496","documentation":"Panic while converting a Postgres row to ProxyRow: a column matched as INT/SERIAL/INT4 is decoded with `row.try_get::<i32>(ordinal).expect(\"Failed to get integer\")`. `try_get` fails when the value is NULL (scalar i32 target rejects NULL with `UnexpectedNullError`) or the runtime value cannot decode as i32 despite the reported type name (e.g. a DOMAIN over integer or a shadowed type).","triggerScenarios":"Reading a nullable int4 column (including LEFT JOIN misses or nullable view columns) through ProxyRow; querying a Postgres DOMAIN over integer whose decode target doesn't match; serial columns in a result where NULL slipped in via an outer join.","commonSituations":"Nullable foreign-key columns read directly through raw/ProxyRow queries; views exposing nullable projections of NOT NULL base columns; DOMAIN types over integer used for enums; search_path shadowing of builtin types.","solutions":["Decode as Option: `row.try_get::<Option<i32>, _>(c.ordinal())` and map to `Value::Int(opt)`.","COALESCE the column in SQL when NULL should become a default (0).","ALTER TABLE ... SET NOT NULL (with DEFAULT) on columns guaranteed non-null.","Cast away DOMAINs (`col::integer`) so the sqlx decode target matches i32.","Inspect `pg_typeof(col)` / search_path for shadowed types and fix schema or the match arm."],"exampleFix":"// before (panics on NULL)\n\"INT\" | \"SERIAL\" | \"INT4\" => Value::Int(row.try_get(c.ordinal()).expect(\"Failed to get integer\")),\n// after (NULL-safe)\n\"INT\" | \"SERIAL\" | \"INT4\" => Value::Int(\n    row.try_get::<Option<i32>, _>(c.ordinal())\n        .expect(\"Failed to get integer\")\n        .unwrap_or_default(),\n),","handlingStrategy":"try-catch","validationCode":"// SELECT column_name, is_nullable, data_type FROM information_schema.columns\n//   WHERE table_name = 't' AND data_type = 'integer';\nlet type_name = col.type_info().name().to_string();\ndebug_assert!(matches!(type_name.as_str(), \"INT\" | \"SERIAL\" | \"INT4\"));","typeGuard":"fn as_i32(row: &ProxyRow, col: &str) -> Option<i32> {\n    match row.value(col) {\n        Some(Value::Int(v)) => v,\n        _ => None,\n    }\n}","tryCatchPattern":"let result = std::panic::catch_unwind(|| proxy_row_get_i32(&row, \"parent_id\"));\nmatch result {\n    Ok(v) => v,\n    Err(_) => treat_as_null_or_default(), // nullable FK: treat as None\n}","preventionTips":["Map nullable FK/int columns to Option<i32>, never scalar i32, in raw queries.","COALESCE or LEFT-JOIN-proof queries to avoid unexpected NULLs.","SET NOT NULL + DEFAULT on integer columns the model guarantees.","Cast DOMAINs over integer to base integer in SQL."],"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"}