gofr-dev/gofr · error
failed to marshal value to JSON: %w
Error message
failed to marshal value to JSON: %w
What it means
ToJSON marshals a Go value to a JSON string for use with KVStore.Set. This error wraps json.Marshal failures with 'failed to marshal value to JSON: %w' when the value contains types JSON cannot represent.
Source
Thrown at pkg/gofr/datasource/kv-store/dynamodb/dynamo.go:126
// UseMetrics sets the metrics for the Dynamo client which asserts the Metrics interface.
func (c *Client) UseMetrics(metrics any) {
if m, ok := metrics.(Metrics); ok {
c.metrics = m
}
}
// UseTracer sets the tracer for Dynamo client.
func (c *Client) UseTracer(tracer any) {
if tracer, ok := tracer.(trace.Tracer); ok {
c.tracer = tracer
}
}
// ToJSON converts a Go struct to JSON string for use with KVStore.Set.
func ToJSON(value any) (string, error) {
jsonData, err := json.Marshal(value)
if err != nil {
return "", fmt.Errorf("failed to marshal value to JSON: %w", err)
}
return string(jsonData), nil
}
// FromJSON converts a JSON string to a Go struct for use with KVStore.Get.
func FromJSON(jsonData string, dest any) error {
if err := json.Unmarshal([]byte(jsonData), dest); err != nil {
return fmt.Errorf("failed to unmarshal JSON: %w", err)
}
return nil
}
func (c *Client) Get(ctx context.Context, key string) (string, error) {
if !c.connected {
return "", errClientNotConnected
}View on GitHub (pinned to 187eb24962)
Solutions
- Remove or tag unmarshalable fields (chan, func) with json:"-" so the marshaler skips them
- Convert NaN/Inf floats to valid numbers or omit them before calling ToJSON
- Call ToJSON first and log the wrapped %w cause to identify the offending field
- Pre-serialize in tests (Test_ToJSONError pattern) to catch bad shapes early
Example fix
// before
type Session struct { Done chan struct{} }
s, _ := ToJSON(Session{}) // error
// after
type Session struct { Done chan struct{} `json:"-"` }
s, err := ToJSON(Session{}) Defensive patterns
Strategy: validation
Validate before calling
func jsonSafe(v any) error {
rv := reflect.ValueOf(v)
for rv.Kind() == reflect.Ptr { rv = rv.Elem() }
if rv.Kind() == reflect.Struct {
for i := 0; i < rv.NumField(); i++ {
switch rv.Field(i).Kind() {
case reflect.Chan, reflect.Func, reflect.Complex64, reflect.Complex128:
return fmt.Errorf("field %s not JSON-serializable", rv.Type().Field(i).Name)
}
}
}
return nil
} Type guard
func isMarshalable(v any) bool { _, err := json.Marshal(v); return err == nil } Try / catch
s, err := dynamodb.ToJSON(value)
if err != nil {
var ue *json.UnsupportedTypeError
if errors.As(err, &ue) { log.Printf("unsupported type: %v", ue.Value); return nil, err }
return nil, err
} Prevention
- Keep chan/func fields out of stored structs or tag them json:"-"
- Sanitize NaN/Inf floats before storing
- Write a unit test that round-trips every stored struct via ToJSON/FromJSON
- Log the wrapped %w cause to pinpoint the offending field
When it happens
Trigger: Calling ToJSON with a struct containing channels, functions, complex numbers, or NaN/Inf floats; passing a value with unmarshalable custom MarshalJSON that errors; cyclic data handled by marshal returning an error.
Common situations: Passing structs with func or chan fields (e.g. logger, connection handles) straight to Set, NaN from float math, time.Time in unusual layouts is fine but custom marshalers returning errors are not.
Related errors
- failed to unmarshal JSON: %w
- client not connected, call Connect() first
- key not found
- %w: %s
- status down
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/a7fce6f98f3ca79f.
Report an issue: GitHub.