jackc/pgx · error

simple protocol queries must be run with client_encoding=UTF

Error message

simple protocol queries must be run with client_encoding=UTF8

What it means

Returned by sanitizeForSimpleQuery when the session's client_encoding is not 'UTF8'. Client-side SQL sanitization (simple protocol) assumes UTF-8 so byte-level escaping of string literals is correct; any other encoding could mis-escape and produce malformed or injectable SQL. pgx refuses rather than guess.

Source

Thrown at conn.go:1270

	if err != nil {
		return &pipelineBatchResults{ctx: ctx, conn: c, err: err, closed: true}
	}

	return &pipelineBatchResults{
		ctx:      ctx,
		conn:     c,
		pipeline: pipeline,
		b:        b,
	}
}

func (c *Conn) sanitizeForSimpleQuery(sql string, args ...any) (string, error) {
	if c.pgConn.ParameterStatus("standard_conforming_strings") != "on" {
		return "", errors.New("simple protocol queries must be run with standard_conforming_strings=on")
	}

	if c.pgConn.ParameterStatus("client_encoding") != "UTF8" {
		return "", errors.New("simple protocol queries must be run with client_encoding=UTF8")
	}

	var err error
	valueArgs := make([]any, len(args))
	for i, a := range args {
		valueArgs[i], err = convertSimpleArgument(c.typeMap, a)
		if err != nil {
			return "", err
		}
	}

	return sanitize.SanitizeSQL(sql, valueArgs...)
}

// LoadType inspects the database for typeName and produces a [pgtype.Type] suitable for registration. typeName must be
// the name of a type where the underlying type(s) is already understood by pgx. It is for derived types. In particular,
// typeName must be one of the following:
//   - An array type name of a type that is already registered. e.g. "_foo" when "foo" is registered.

View on GitHub (pinned to ec1a0befd2)

Solutions

  1. Remove any SET client_encoding=... that moves away from UTF8; let it default to UTF8.
  2. Set the server default client_encoding to UTF8 in postgresql.conf.
  3. Switch DefaultQueryExecMode to an extended-protocol mode so pgx binds parameters binary-wise and encoding of literal text no longer matters to sanitization.
  4. After connect, verify SHOW client_encoding returns UTF8 and fail fast otherwise.

Example fix

// before
config.DefaultQueryExecMode = pgx.QueryExecModeExec
// session has SET client_encoding='LATIN1'

// after
config.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
// and ensure client_encoding stays UTF8
Defensive patterns

Strategy: validation

Validate before calling

var ce string
if err := conn.QueryRow(ctx, "SHOW client_encoding").Scan(&ce); err != nil { return err }
if ce != "UTF8" { return fmt.Errorf("refusing simple-protocol: client_encoding=%q", ce) }

Type guard

func utf8ForSimpleProtocol(c *pgx.Conn) bool {
    return c.PgConn().ParameterStatus("client_encoding") == "UTF8"
}

Try / catch

if err != nil && strings.Contains(err.Error(), "client_encoding=UTF8") {
    cfg.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement // bypass sanitization
}

Prevention

When it happens

Trigger: Running simple-protocol queries against a session whose client_encoding GUC has been changed away from UTF8 (e.g. SET client_encoding='LATIN1'; or a server/pooler that negotiates a non-UTF8 client encoding).

Common situations: A legacy database or middleware that sets client_encoding to a regional encoding (LATIN1, SQL_ASCII, WIN1252); a connection pooler that injects encoding setup; restoring a dump that ran SET client_encoding.

Related errors


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