geektutu/7days-golang · error

err.Error()

Error message

err.Error()

What it means

This error surfaces inside Context.JSON when encoding.Engine.Encode fails to serialize the response object to JSON. The gee framework's JSON helper writes the object to the http.ResponseWriter; if the object contains values Go's encoding/json cannot marshal (e.g. channels, funcs, cyclic structures) or if the write fails mid-stream, Encode returns an error. The handler then writes the raw error message to the response with HTTP 500 via http.Error.

Source

Thrown at gee-web/day6-template/gee/context.go:84

	c.Writer.WriteHeader(code)
}

func (c *Context) SetHeader(key string, value string) {
	c.Writer.Header().Set(key, value)
}

func (c *Context) String(code int, format string, values ...interface{}) {
	c.SetHeader("Content-Type", "text/plain")
	c.Status(code)
	c.Writer.Write([]byte(fmt.Sprintf(format, values...)))
}

func (c *Context) JSON(code int, obj interface{}) {
	c.SetHeader("Content-Type", "application/json")
	c.Status(code)
	encoder := json.NewEncoder(c.Writer)
	if err := encoder.Encode(obj); err != nil {
		http.Error(c.Writer, err.Error(), 500)
	}
}

func (c *Context) Data(code int, data []byte) {
	c.Status(code)
	c.Writer.Write(data)
}

// HTML template render
// refer https://golang.org/pkg/html/template/
func (c *Context) HTML(code int, name string, data interface{}) {
	c.SetHeader("Content-Type", "text/html")
	c.Status(code)
	if err := c.engine.htmlTemplates.ExecuteTemplate(c.Writer, name, data); err != nil {
		c.Fail(500, err.Error())
	}
}

View on GitHub (pinned to cf36443821)

Solutions

  1. Fix the payload: ensure the object passed to c.JSON contains only JSON-serializable types (no channels, funcs, complex numbers, or cycles).
  2. Add json:"field" tags and export fields on structs so marshaling produces expected output.
  3. Implement json.Marshaler or pre-validate with json.Marshal(obj) in development/tests to catch unsupported types before writing headers.
  4. Check whether the client disconnected (broken pipe); in that case log the error server-side rather than treating it as a payload bug.
  5. Centralize the error: replace http.Error(500) with the framework's Fail/Abort helper so headers are set consistently.

Example fix

// before
c.JSON(http.StatusOK, map[string]interface{}{
    "conn": someNetConn, // json: unsupported type
})
// after
c.JSON(http.StatusOK, map[string]interface{}{
    "conn": someNetConn.RemoteAddr().String(),
})
Defensive patterns

Strategy: validation

Validate before calling

func canMarshal(obj interface{}) error {
    _, err := json.Marshal(obj)
    return err
}
// call before responding:
if err := canMarshal(payload); err != nil {
    log.Printf("payload not JSON-serializable: %v", err)
    return
}

Type guard

func isJSONSafe(v interface{}) bool {
    switch v.(type) {
    case chan struct{}, chan int, func(), complex64, complex128:
        return false
    }
    return true
}

Try / catch

// Go has no try/catch; handle the returned error explicitly
if err := encoder.Encode(obj); err != nil {
    if errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) {
        log.Printf("client disconnected: %v", err)
    } else {
        log.Printf("json encode failed: %v", err)
        http.Error(c.Writer, "internal server error", 500)
    }
}

Prevention

When it happens

Trigger: Calling c.JSON(code, obj) where obj contains unsupported types (channel, func, complex), has a cyclic reference causing a json.UnsupportedTypeError/json.MarshalerError, or where the client has disconnected so the underlying Write to c.Writer fails.

Common situations: Returning structs with unexported-only fields plus invalid data, accidentally passing a channel or function value, embedding a cyclic pointer graph (e.g. parent/child linked nodes), or returning very large responses to clients that timed out and closed the connection.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/6ec8e610b530fcbd. Report an issue: GitHub.