jackc/pgx · error

simple protocol queries must be run with standard_conforming

Error message

simple protocol queries must be run with standard_conforming_strings=on

What it means

Returned by (*Conn).sanitizeForSimpleQuery before client-side parameter interpolation when the server's standard_conforming_strings GUC is not 'on'. pgx only sanitizes simple-protocol queries when backslash escapes are disabled (standard_conforming_strings=on), because off-mode would let backslashes change string semantics and break the escaping logic — a potential SQL-injection vector. The guard is defensive; PostgreSQL has defaulted this to on since 9.1.

Source

Thrown at conn.go:1266

		}
	}

	err := pipeline.Sync()
	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...)
}

View on GitHub (pinned to ec1a0befd2)

Solutions

  1. Ensure the server/cluster default is standard_conforming_strings=on (it has been since PG 9.1) and remove any SET standard_conforming_strings=off.
  2. Switch the connection's DefaultQueryExecMode away from QueryExecModeExec (simple protocol) to an extended-protocol mode (CacheStatement/CacheDescribe/DescribeExec/Exec), which binds parameters safely without sanitization.
  3. After connecting, run SHOW standard_conforming_strings and fail fast if it is not 'on' so misconfigured sessions are caught early.
  4. If a legacy app needs off-mode, separate that workload onto its own connection with extended-protocol mode.

Example fix

// before
config.DefaultQueryExecMode = pgx.QueryExecModeExec // simple protocol

// after — use extended protocol (default), bypassing sanitization
config.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

func safeForSimpleProtocol(c *pgx.Conn) bool {
    return c.PgConn().ParameterStatus("standard_conforming_strings") == "on"
}

Try / catch

_, err := conn.Exec(ctx, sql, args...)
if err != nil && strings.Contains(err.Error(), "standard_conforming_strings=on") {
    // switch off simple protocol or fix the GUC
    cfg.DefaultQueryExecMode = pgx.QueryExecModeCacheStatement
}

Prevention

When it happens

Trigger: Executing a query in QueryExecModeExec (simple protocol) — or otherwise hitting sanitizeForSimpleQuery (conn.go:586/863/1027/1264) — against a server or session where standard_conforming_strings is off, e.g. set explicitly via SET standard_conforming_strings=off; or a legacy/old cluster.

Common situations: A migration or DBA script that issues SET standard_conforming_strings=off for backward compatibility; an inherited PostgreSQL 8.x/9.0 era cluster config; a pooler that reconfigures session GUCs; a test database with legacy settings.

Related errors


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