chenhg5/cc-connect · error

encode rpc message: %w

Error message

encode rpc message: %w

What it means

writeRPCMessage marshals an outgoing JSON-RPC payload (params or notification) with encoding/json and failed, returning a wrapped "encode rpc message" error. Marshal only fails for values the JSON encoder cannot represent (channels, funcs, cyclic structures, or invalid types like NaN in float fields), so this points to a bad payload constructed before the call.

Source

Thrown at agent/codex/session.go:779

			}
		}
		return nil
	}
}

func rpcNotifyOverIO(stdin io.Writer, method string, params any) error {
	payload := map[string]any{
		"jsonrpc": "2.0",
		"method":  method,
		"params":  params,
	}
	return writeRPCMessage(stdin, payload)
}

func writeRPCMessage(w io.Writer, payload any) error {
	b, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("encode rpc message: %w", err)
	}
	if _, err := w.Write(append(b, '\n')); err != nil {
		return fmt.Errorf("write rpc message: %w", err)
	}
	return nil
}

// RespondPermission is a no-op for Codex — permissions are handled via CLI flags.
func (cs *codexSession) RespondPermission(_ string, _ core.PermissionResult) error {
	return nil
}

func (cs *codexSession) Events() <-chan core.Event {
	return cs.events
}

func (cs *codexSession) CurrentSessionID() string {
	v, _ := cs.threadID.Load().(string)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the payload type being passed to rpcRequestOverIO/rpcNotifyOverIO and ensure all fields are JSON-serializable.
  2. Check for NaN/Inf float values or cyclic references introduced by recent code changes.
  3. Validate the marshaling with a small test: `json.Marshal(params)` and inspect the error text, which names the offending Go type.
  4. Upgrade or downgrade to a matching connector/codex version combination if this started after an update (struct drift).

Example fix

// before: unmarshalable field
params := struct{ At time.Time }{At: time.Now()} // ok, but ensure no channels/funcs
// after: verify serialization before send
if _, err := json.Marshal(params); err != nil {
    return fmt.Errorf("codex: invalid rpc params: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// validate payload serializability before sending
if _, err := json.Marshal(payload); err != nil {
    return fmt.Errorf("rpc payload not JSON-serializable: %w", err)
}

Type guard

func isMarshalable(v any) bool {
    _, err := json.Marshal(v)
    return err == nil
}

Try / catch

err := rpcNotifyOverIO(stdin, ctx, "initialized")
if err != nil && strings.Contains(err.Error(), "encode rpc message") {
    slog.Error("rpc payload contains unmarshalable values", "err", err)
    // fix payload construction; a retry with the same payload will fail identically
}

Prevention

When it happens

Trigger: json.Marshal(payload) returns an error inside writeRPCMessage, called from rpcRequestOverIO or rpcNotifyOverIO when sending a request/notification to the codex app-server.

Common situations: A params struct gained an unsupported field type (e.g. json.Number misuse, cyclic pointer graph); NaN/Inf floats in numeric options; passing an unsupported value type as a param.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/4fb2d701845bd21d. Report an issue: GitHub.