gofr-dev/gofr · error
failed to unmarshal JSON: %w
Error message
failed to unmarshal JSON: %w
What it means
FromJSON decodes a JSON string into dest for use with KVStore.Get. This error wraps json.Unmarshal failures with 'failed to unmarshal JSON: %w' when the stored string is invalid JSON or incompatible with dest's shape.
Source
Thrown at pkg/gofr/datasource/kv-store/dynamodb/dynamo.go:135
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
}
span := c.addTrace(ctx, "get", key)
defer c.sendOperationsStats(time.Now(), "GET", "get", span, key)
input := &dynamodb.GetItemInput{
TableName: aws.String(c.configs.Table),
Key: map[string]types.AttributeValue{
c.configs.PartitionKeyName: &types.AttributeValueMemberS{Value: key},
},View on GitHub (pinned to 187eb24962)
Solutions
- Always write with ToJSON so stored values are valid JSON
- Pass a dest whose fields match the stored JSON types; check the wrapped err for a *json.UnmarshalTypeError detail
- Handle legacy/plain-string values: attempt FromJSON and fall back to raw string handling
- Validate the stored value is non-empty before unmarshaling
Example fix
// before
var u User
err := FromJSON(raw, &u) // fails on plain text
// after
var u User
if err := FromJSON(raw, &u); err != nil {
u = User{Name: raw} // fallback for legacy raw values
} Defensive patterns
Strategy: validation
Validate before calling
func validJSON(s string) error {
if s == "" { return errors.New("empty JSON") }
if !json.Valid([]byte(s)) { return errors.New("invalid JSON payload") }
return nil
}
// call before FromJSON: if err := validJSON(raw); err != nil { handle } Type guard
func canUnmarshal[T any](s string) bool { var v T; return json.Unmarshal([]byte(s), &v) == nil } Try / catch
var dest MyStruct
if err := dynamodb.FromJSON(raw, &dest); err != nil {
var te *json.UnmarshalTypeError
if errors.As(err, &te) { log.Printf("type mismatch at %v", te.Field) }
return fallbackDecode(raw)
} Prevention
- Write all values through ToJSON so the store holds valid JSON
- Version your stored structs to survive schema drift
- Reject/truncate-proof: never store empty strings for JSON values
- Add round-trip tests (Test_FromJSONError style) for stored types
When it happens
Trigger: Calling FromJSON on a value that was Set as a raw string rather than via ToJSON; dest type not matching stored JSON (e.g. number into string field); empty or truncated stored value; malformed JSON written by another writer.
Common situations: Mixed writers to the same KV store (one uses ToJSON, one stores plain text), schema drift after struct field renames/type changes, reading keys written by an older app version.
Related errors
- failed to marshal value to 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/bfca487157279244.
Report an issue: GitHub.