glanceapp/glance · error
body must be a string when body-type is 'string'
Error message
body must be a string when body-type is 'string'
What it means
The Custom API widget's .JSON option helper marshals the option value with encoding/json and panics with 'marshaling %s: %v' if json.Marshal fails. The template engine recovers the panic into a render error. Standard YAML-sourced values (strings, numbers, bools, maps, lists) always marshal; failures come from values JSON cannot represent.
Source
Thrown at internal/glance/widget-custom-api.go:163
req.BodyType = "json"
}
if req.BodyType != "json" && req.BodyType != "string" {
return errors.New("invalid body type, must be either 'json' or 'string'")
}
switch req.BodyType {
case "json":
encoded, err := json.Marshal(req.Body)
if err != nil {
return fmt.Errorf("marshaling body: %v", err)
}
req.bodyReader = bytes.NewReader(encoded)
case "string":
bodyAsString, ok := req.Body.(string)
if !ok {
return errors.New("body must be a string when body-type is 'string'")
}
req.bodyReader = strings.NewReader(bodyAsString)
}
} else if req.Method == "" {
req.Method = http.MethodGet
}
httpReq, err := http.NewRequest(strings.ToUpper(req.Method), req.URL, req.bodyReader)
if err != nil {
return err
}
if len(req.Parameters) > 0 {
httpReq.URL.RawQuery = req.Parameters.toQueryString()
}
View on GitHub (pinned to 91324e8de7)
Solutions
- Replace .nan/.inf option values with real numbers, strings, or null and handle absence in the template
- If a number may be unknown, store it as a string or omit the key and use .FloatOr default
- Sanitize computed values with {{ if ... }} guards before passing to .JSON
Example fix
// before (glance.yml)
options:
ratio: .nan
# template: {{ .JSON "ratio" }}
// after
options:
ratio: 0.0
# or omit the key and use a default in the template Defensive patterns
Strategy: validation
Validate before calling
if math.IsNaN(f) || math.IsInf(f, 0) {
return errors.New("value not representable in JSON")
}
b, err := json.Marshal(f) Type guard
func jsonMarshalable(v any) bool {
_, err := json.Marshal(v)
return err == nil
} Try / catch
Wrap the .JSON call site in template logic that only runs for known-safe values; in Go code, pre-check non-finite floats with math.IsNaN/IsInf before marshaling, since encoding/json has no option to tolerate them.
Prevention
- Never use .nan/.inf in YAML options that flow into .JSON
- Represent unknown numbers as null, a string, or omit the key and use .FloatOr defaults
- Test custom-api templates against the exact options payload used in production
When it happens
Trigger: An option value that encoding/json rejects — most notably float NaN/Infinity (YAML .nan or .inf) — is passed to .JSON. marshal fails with 'json: unsupported value: NaN' and the panic fires.
Common situations: YAML config using .nan/.inf placeholders for 'unknown' numbers that then get embedded into a JSON request body via .JSON; values computed in a template pipeline that produce non-finite floats; options populated from upstream data containing non-finite numbers.
Related errors
- invalid body type, must be either 'json' or 'string'
- invalid response JSON
- missing API token
- marshaling body: %v
- usernames must be at least 3 characters
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/7557993bea749abe.
Report an issue: GitHub.