jackc/pgx · error
tried to encode via encoding to text and scanning but…
Error message
tried to encode %v via encoding to text and scanning but failed due to receiving same type back
What it means
When a value cannot be encoded directly, the fallback machinery encodes it to text, scans that text into an any, and retries encoding with the now-concrete type. This guard is the infinite-loop breaker: if the scanned value comes back the same Go type as the original (e.g. a string that stays a string), no progress is possible and encoding is abandoned (see pgx issue #1331).
Solutions
- Convert the value to a type with a registered encode plan before passing it
- Register an encode plan or wrapper for the value's type
- Use a string in the target text format or []byte instead of an ambiguous type
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at pgtype/pgtype.go:1333 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/76140289af849143.
Report an issue: GitHub.
Appendix: source
Thrown at pgtype/pgtype.go:1333
newBuf, err = plan.m.Encode(plan.oid, plan.formatCode, v, buf)
if err == nil {
return newBuf, nil
}
s, ok := v.(string)
if !ok {
return nil, err
}
var scannedValue any
scanErr := plan.m.Scan(plan.oid, TextFormatCode, []byte(s), &scannedValue)
if scanErr != nil {
return nil, err
}
// Prevent infinite loop. We can't encode this. See https://github.com/jackc/pgx/issues/1331.
if reflect.TypeOf(value) == reflect.TypeOf(scannedValue) {
return nil, fmt.Errorf("tried to encode %v via encoding to text and scanning but failed due to receiving same type back", value)
}
var err2 error
newBuf, err2 = plan.m.Encode(plan.oid, BinaryFormatCode, scannedValue, buf)
if err2 != nil {
return nil, err
}
return newBuf, nil
}
// TryWrapEncodePlanFunc is a function that tries to create a wrapper plan for value. If successful it returns a plan
// that will convert the value passed to Encode and then call the next plan. nextValue is value as it will be converted
// by plan. It must be used to find another suitable EncodePlan. When it is found SetNext must be called on plan for it
// to be usabled. ok indicates if a suitable wrapper was found.
type TryWrapEncodePlanFunc func(value any) (plan WrappedEncodePlanNextSetter, nextValue any, ok bool)
type derefPointerEncodePlan struct {View on GitHub (pinned to ec1a0befd2)