jackc/pgx · error

invalid write to large object

Error message

invalid write to large object

What it means

Returned by LargeObject.Write when lowrite reports a count strictly greater than the bytes requested (large_objects.go:101-102). This is logically impossible for a correct server — lowrite cannot write more bytes than were supplied. Its presence indicates a server bug, a corrupted response, or a protocol/codec desync where the scanned int does not represent the real byte count.

Source

Thrown at large_objects.go:102

			expected = maxLargeObjectMessageLength
		}

		var n int
		err := o.tx.QueryRow(o.ctx, "select lowrite($1, $2)", o.fd, p[nTotal:nTotal+expected]).Scan(&n)
		if err != nil {
			return nTotal, err
		}

		if n < 0 {
			return nTotal, errors.New("failed to write to large object")
		}

		nTotal += n

		if n < expected {
			return nTotal, errors.New("short write to large object")
		} else if n > expected {
			return nTotal, errors.New("invalid write to large object")
		}
	}

	return nTotal, nil
}

// Read reads up to len(p) bytes into p returning the number of bytes read.
func (o *LargeObject) Read(p []byte) (int, error) {
	nTotal := 0
	for {
		expected := len(p) - nTotal
		if expected == 0 {
			break
		} else if expected > maxLargeObjectMessageLength {
			expected = maxLargeObjectMessageLength
		}

		res := pgtype.PreallocBytes(p[nTotal:])

View on GitHub (pinned to ec1a0befd2)

Solutions

  1. Capture the exact n and expected values; this is almost always a server/extension bug worth reporting upstream.
  2. Confirm no custom codec is intercepting the int32 return of lowrite.
  3. Restart the connection / try a different PostgreSQL version to rule out a transient server fault.
  4. File an issue against pgx only after ruling out server/extension causes; include server version and the failing payload size.
Defensive patterns

Strategy: try-catch

Try / catch

if _, err := lo.Write(p); err != nil {
    if err.Error() == "invalid write to large object" {
        // impossible-by-construction; treat as fatal protocol error
        // reconnect or abort transaction, file a bug report
    }
    return err
}

Prevention

When it happens

Trigger: The int32 scanned from lowrite exceeds the supplied chunk size, tripping the n > expected branch. Reachable only via server/protocol misbehavior.

Common situations: A buggy or experimental PostgreSQL extension overriding lowrite; protocol-level corruption desynchronizing the result reader; a custom type codec mis-decoding the lowrite return value; extremely rare server-side fault.

Related errors


AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04). Data as JSON: /data/errors/22fced60b6487f03.json. Report an issue: GitHub.