jackc/pgx · error

invalid length for Close.ObjectType

Error message

invalid length for Close.ObjectType

What it means

Returned by Close.UnmarshalJSON when the JSON `ObjectType` field is not exactly one character long. In the wire protocol ObjectType is a single byte ('S' for prepared statement, 'P' for portal), so the JSON representation requires a single-character string. Anything else (empty string, a multi-char word like "statement", or a number) is rejected.

Source

Thrown at pgproto3/close.go:75

}

// UnmarshalJSON implements encoding/json.Unmarshaler.
func (dst *Close) UnmarshalJSON(data []byte) error {
	// Ignore null, like in the main JSON package.
	if string(data) == "null" {
		return nil
	}

	var msg struct {
		ObjectType string
		Name       string
	}
	if err := json.Unmarshal(data, &msg); err != nil {
		return err
	}

	if len(msg.ObjectType) != 1 {
		return errors.New("invalid length for Close.ObjectType")
	}

	dst.ObjectType = msg.ObjectType[0]
	dst.Name = msg.Name
	return nil
}

View on GitHub (pinned to ec1a0befd2)

Solutions

  1. Use the single-character wire form: "S" for prepared statement, "P" for portal.
  2. If your JSON source uses full words, map them before unmarshalling: `"statement" -> "S"`, `"portal" -> "P"`.
  3. Validate the JSON shape with a schema or a pre-unmarshal check that `len(objType) == 1` and report a clearer error to the caller.
  4. Regenerate any recorded fixtures with the library's own MarshalJSON so the field shape always matches.

Example fix

// before
raw := []byte(`{"ObjectType":"statement","Name":"foo"}`)
err := json.Unmarshal(raw, &closeMsg) // error

// after
raw := []byte(`{"ObjectType":"S","Name":"foo"}`)
err := json.Unmarshal(raw, &closeMsg)
Defensive patterns

Strategy: validation

Validate before calling

func validateCloseJSON(raw []byte) error {
	var probe struct{ ObjectType string }
	if err := json.Unmarshal(raw, &probe); err != nil { return err }
	if len(probe.ObjectType) != 1 {
		return fmt.Errorf("ObjectType must be a single char (\"S\" or \"P\"), got %q", probe.ObjectType)
	}
	return nil
}

Type guard

func isValidCloseObjectType(s string) bool {
	return len(s) == 1 && (s == "S" || s == "P")
}

Try / catch

var c pgproto3.Close
if err := json.Unmarshal(raw, &c); err != nil {
    // log err mentioning ObjectType must be "S" or "P"
    return err
}

Prevention

When it happens

Trigger: Calling `json.Unmarshal(data, &closeMsg)` on JSON where the `ObjectType` field has length != 1 — e.g. `{"ObjectType": "statement"}` or `{"ObjectType": ""}`.

Common situations: Test fixtures or recording/replay tools produce JSON with a human-readable ObjectType ("statement"/"portal") instead of the single-letter wire form. Also seen when a JSON generator omits ObjectType or encodes it as a numeric code.

Related errors


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