{"record":{"id":"a11653ca99481da7","repo":"tursodatabase/turso","slug":"cannot-convert-remote-type-value-to-decimal","errorCode":null,"errorMessage":"Cannot convert remote {Type} value to Decimal.","messagePattern":"Cannot convert remote (.+?) value to Decimal\\.","errorType":"exception","errorClass":"InvalidCastException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoRemoteClient.cs","lineNumber":698,"sourceCode":"    public double GetDouble()\n    {\n        return Type switch\n        {\n            \"float\" => ParseFloat(),\n            \"integer\" => ParseInteger(),\n            \"text\" => double.Parse(Value.GetString() ?? \"\", CultureInfo.InvariantCulture),\n            _ => throw new InvalidCastException($\"Cannot convert remote {Type} value to Double.\"),\n        };\n    }\n\n    public decimal GetDecimal()\n    {\n        return Type switch\n        {\n            \"float\" => Convert.ToDecimal(ParseFloat(), CultureInfo.InvariantCulture),\n            \"integer\" => ParseInteger(),\n            \"text\" => decimal.Parse(Value.GetString() ?? \"\", CultureInfo.InvariantCulture),\n            _ => throw new InvalidCastException($\"Cannot convert remote {Type} value to Decimal.\"),\n        };\n    }\n\n    private long ParseInteger()\n    {\n        return Value.ValueKind == JsonValueKind.String\n            ? long.Parse(Value.GetString() ?? \"\", CultureInfo.InvariantCulture)\n            : Value.GetInt64();\n    }\n\n    private double ParseFloat()\n    {\n        return Value.ValueKind == JsonValueKind.String\n            ? double.Parse(Value.GetString() ?? \"\", CultureInfo.InvariantCulture)\n            : Value.GetDouble();\n    }\n\n    private static byte[] DecodeBase64(string value)","sourceCodeStart":680,"sourceCodeEnd":716,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data/TursoRemoteClient.cs#L680-L716","documentation":"GetDecimal on a reader column whose remote value type is not float, integer, or text. The remote protocol has no decimal type -- floats and text are converted -- but NULL and BLOB have no arm, so those cells throw InvalidCastException from the typed getter.","triggerScenarios":"reader.GetDecimal(i) on a remote connection where column i is NULL, a BLOB, or an unsupported type; text cells are parsed with decimal.Parse and throw FormatException for non-numeric or culture-incompatible strings.","commonSituations":"Money/amount columns stored as REAL or TEXT and occasionally NULL; LEFT JOIN or outer-aggregate queries producing NULL cells; schema changes after deployment.","solutions":["Guard with reader.IsDBNull(i) before GetDecimal and choose a default (0m or throwing a domain-specific error).","Use COALESCE(col, 0) in SQL when a zero default is acceptable.","Prefer storing money as integer minor units or TEXT and converting explicitly, since the wire protocol has no exact decimal type.","Verify the column ordinal and declared type before using typed getters."],"exampleFix":"// before\ndecimal total = reader.GetDecimal(2);\n\n// after\ndecimal total = reader.IsDBNull(2) ? 0m : reader.GetDecimal(2);","handlingStrategy":"validation","validationCode":"if (reader.IsDBNull(ordinal))\n    return 0m;\nreturn reader.GetDecimal(ordinal);","typeGuard":"static bool CanReadDecimal(System.Data.Common.DbDataReader reader, int i) =>\n    !reader.IsDBNull(i)\n    && reader.GetFieldType(i) is Type t\n    && (t == typeof(decimal) || t == typeof(double) || t == typeof(long) || t == typeof(string));","tryCatchPattern":"try { value = reader.GetDecimal(i); }\ncatch (InvalidCastException) when (reader.IsDBNull(i))\n{\n    value = 0m; // explicit policy for NULL money columns\n}","preventionTips":["Store money as integer minor units or well-formed TEXT, since the wire protocol has no exact decimal type.","Wrap nullable amount columns in COALESCE at the query level when zero is a sane default.","Check IsDBNull before every GetDecimal on nullable columns.","Culture-proof text-to-decimal parsing: the binding parses invariantly, so store canonical formats."],"tags":["turso","dotnet","reader","invalid-cast","null-handling","decimal"],"backgroundTag":"invalid-cast-exception","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}