Sitelet https://github.com/npgsql/npgsql/issues/6383
Skip to content

NpgsqlBinaryExporter function throws exception when reading BigInteger. #6383

Description

@SoftStoneDevelop
Table

CREATE TABLE public.bigintegernumeric
(
    value numeric NOT NULL
);

Import method

        private static async Task ImportAsync(NpgsqlDataSource npgsqlDataSource, IEnumerable<BigNumberModel> collection)
        {
            await using var connection = await npgsqlDataSource.OpenConnectionAsync();
            NpgsqlBinaryImporter import = null;
            try
            {
                import = connection.BeginBinaryImport(@"

COPY public.bigintegernumeric
(
value
) 
FROM STDIN (FORMAT BINARY)

");

                foreach (var item in collection)
                {
                    import.StartRow();
                    import.Write(item.BigInteger, NpgsqlTypes.NpgsqlDbType.Numeric);
                }
                import.Complete();
                import.Dispose();
                import = null;
            }
            finally
            {
                if (import != null)
                {
                    try
                    {
                        import.Close();
                    }
                    catch { /* ignore */ }

                    import.Dispose();
                }
            }
        }

Export method

        private static async Task<List<BigNumberModel>> ExportAsync(NpgsqlDataSource npgsqlDataSource)
        {
            await using var connection = await npgsqlDataSource.OpenConnectionAsync();
            NpgsqlBinaryExporter export = null;
            try
            {
                export = await connection.BeginBinaryExportAsync(@"

COPY public.bigintegernumeric
(
    value
) TO STDOUT (FORMAT BINARY)

");
                var list = new List<BigNumberModel>(); 
                while (await export.StartRowAsync() != -1)
                {
                    var item = new BigNumberModel();
                    item.BigInteger = await export.ReadAsync<System.Numerics.BigInteger>(NpgsqlTypes.NpgsqlDbType.Numeric);

                    list.Add(item);
                }

                await export.DisposeAsync();
                export = null;

                return list;
            }
            finally
            {
                if (export != null)
                {
                    try
                    {
                        await export.CancelAsync();
                    }
                    catch { /* ignore */ }

                    await export.DisposeAsync();
                }
            }
        }

An exception occurs when attempting to execute export:

   at Npgsql.ThrowHelper.ThrowArgumentOutOfRangeException(String paramName, String message)
   at Npgsql.Internal.PgReader.<ShouldBuffer>g__ShouldBufferSlow|115_0(Int32 byteCount)
   at Npgsql.Internal.PgReader.ShouldBuffer(Int32 byteCount)
   at Npgsql.Internal.Converters.NumericConverter.<ReadAsync>d__2.MoveNext()
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
   at Npgsql.Internal.Converters.BigIntegerNumericConverter.<<ReadAsync>g__AsyncCore|2_0>d.MoveNext()
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
   at Npgsql.NpgsqlBinaryExporter.<ReadAsync>d__30`1.MoveNext()
   at Npgsql.NpgsqlBinaryExporter.<ReadAsync>d__30`1.MoveNext()
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at NpgsqlBenchmark.Program.<ExportAsync>d__2.MoveNext() in Program.cs:line 145
   ...
Image

Nothing to have changed in the default type mapping for BigInteger. What am I doing wrong?

Info:
"Npgsql" Version="10.0.1"
TargetFramework: net10.0

Project to reproduce error
https://github.com/SoftStoneDevelop/NpgsqlBinaryExporter/blob/main/Src/NpgsqlBenchmark/Program.cs

Activity

  1. changed the title [-]NpgsqlBinaryExporter throw exception when readed as BigInteger[/-] [+]NpgsqlBinaryExporter function throws exception when reading BigInteger.[/+] on Dec 22, 2025
  2. vonzshik commented on Dec 22, 2025

    @vonzshik
    Contributor

    Looking at the code, I feel like there is an issue with how we read digits on async path:

    var array = digits.Array!;
    for (var i = digits.Offset; i < array.Length; i++)
    {
    if (reader.ShouldBuffer(sizeof(short)))
    await reader.BufferAsync(sizeof(short), cancellationToken).ConfigureAwait(false);
    array[i] = reader.ReadInt16();
    }

    Here, we have an ArraySegment over rented array. The problem is, we iterate starting with ArraySegment.Offset (this is fine) but end with array.Length (which is not, because rented array has a length which is usually more than requested). My guess is that this should be fixed by changing array.Length to digits.Count + digits.Offset.

    cc @NinoFloris

  3. added theissue type on Dec 22, 2025
  4. self-assigned this
    on Dec 22, 2025
  5. added this to the 10.0.2 milestone on Dec 22, 2025
  6. vonzshik commented on Dec 22, 2025

    @vonzshik
    Contributor

    Yes, I can indeed repro the issue and it's exactly what I had in mind. It seems like this is a quite old bug, since I can see the exact same code in Npgsql 8 and 9.

  7. added 4 commits that reference this issue on Dec 23, 2025
    fe4f600
    603024f
    079c3b4
    d16098e
  8. added a commit that references this issue on Dec 23, 2025
    381b0fa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions