jackc/pgx · error · ErrInsufficientBytes

: unterminated string at offset

Error message

%w: unterminated string at offset %d

What it means

Reader.CString found no NUL terminator in the remaining bytes — the wire-format string runs past the end of the message. Wraps ErrInsufficientBytes; the input is truncated or malformed.

Solutions

  1. Verify the message contains the terminating zero byte for the string field
  2. Check for frame truncation upstream of the decoder
  3. Compare the message length prefix against actual payload size
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/pgio/read.go:142 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at internal/pgio/read.go:142

	}
	if !r.need(n) {
		return nil
	}
	b := r.s[r.rp : r.rp+n]
	r.rp += n
	return b
}

// CString reads a NUL-terminated string, returning the bytes before the
// terminator and consuming the terminator. The returned slice aliases the
// source; it is not a copy.
func (r *Reader) CString() []byte {
	if r.err != nil {
		return nil
	}
	i := bytes.IndexByte(r.s[r.rp:], 0)
	if i < 0 {
		r.fail(fmt.Errorf("%w: unterminated string at offset %d", ErrInsufficientBytes, r.rp))
		return nil
	}
	b := r.s[r.rp : r.rp+i]
	r.rp += i + 1
	return b
}

// Count reads an int32 element count and validates it against the remaining
// bytes: the count must be non-negative, and since each element occupies at
// least minElemSize bytes, count*minElemSize must not exceed the remaining
// message. This bounds allocations sized from the count against a malicious
// or corrupt message claiming a huge count. Returns 0 on any failure.
func (r *Reader) Count(minElemSize int) int {
	offset := r.rp
	count := int(r.Int32())
	if r.err != nil {
		return 0
	}

View on GitHub (pinned to ec1a0befd2)