micro/go-micro · error
invalid error %v
Error message
invalid error %v
What it means
The JSON-RPC client's ReadHeader parses the response envelope; the JSON-RPC spec allows the 'error' member to be any JSON value, but this codec only supports string errors. When resp.Error is present but not a JSON string (e.g. an object like {code, message, data} per the JSON-RPC 2.0 spec), ReadHeader returns 'invalid error' and the call fails instead of surfacing the server's error text.
Source
Thrown at codec/jsonrpc/client.go:80
}
func (c *clientCodec) ReadHeader(m *codec.Message) error {
c.resp.reset()
if err := c.dec.Decode(&c.resp); err != nil {
return err
}
c.Lock()
m.Method = c.pending[c.resp.ID]
delete(c.pending, c.resp.ID)
c.Unlock()
m.Error = ""
m.Id = fmt.Sprintf("%v", c.resp.ID)
if c.resp.Error != nil {
x, ok := c.resp.Error.(string)
if !ok {
return fmt.Errorf("invalid error %v", c.resp.Error)
}
if x == "" {
x = "unspecified error"
}
m.Error = x
}
return nil
}
func (c *clientCodec) ReadBody(x interface{}) error {
if x == nil || c.resp.Result == nil {
return nil
}
return json.Unmarshal(*c.resp.Result, x)
}
func (c *clientCodec) Close() error {
return c.c.Close()View on GitHub (pinned to 24529f1404)
Solutions
- Make the server return its error as a plain string in the 'error' field.
- Patch/extend the client to handle object errors (extract 'message' from the object) instead of erroring.
- Use a different transport (e.g. grpc or the micro json codec) that matches the server's error format.
- Log the raw response to confirm the error shape before changing code.
Example fix
// before (server)
return nil, &jsonrpcError{Code: -32600, Message: "bad request"}
// after
return nil, errors.New("bad request") Defensive patterns
Strategy: type-guard
Validate before calling
// Server side: only send string errors so this client can parse them.
// Client side: inspect the raw envelope before decoding if possible.
func errIsString(raw json.RawMessage) bool {
return len(raw) > 0 && raw[0] == '"'
} Type guard
func errAsString(v interface{}) (string, bool) {
s, ok := v.(string)
return s, ok
} Try / catch
if err := client.Call(ctx, req, resp); err != nil {
if strings.HasPrefix(err.Error(), "invalid error") {
// server sent a non-string JSON-RPC error object; inspect raw response
}
return err
} Prevention
- Ensure your JSON-RPC server returns plain-string 'error' values.
- Avoid pairing this client with strict JSON-RPC 2.0 servers that use error objects.
- Pin server/client versions so error formats stay aligned.
- Capture raw responses in a debug mode to diagnose error-shape mismatches.
When it happens
Trigger: Calling a JSON-RPC server that returns a structured error object (JSON-RPC 2.0 style {code:-32600,...}) while this client expects resp.Error to be a plain string.
Common situations: Interoperating with standard JSON-RPC 2.0 servers (Go net/rpc jsonrpc or third-party) that encode errors as objects; proxying requests to services using the official spec; version mismatch between client expectations and server implementation.
Related errors
- unrecognized message type: %v
- ErrInvalidMessage
- unknown request path
- unsupported Content-Type
- failed to marshal: %v is not type of *bytes.Frame or proto.M
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/7377bac3ad72a5e5.
Report an issue: GitHub.