semaphoreui/semaphore · error
must be valid JSON
Error message
must be valid JSON
What it means
validateJSON parses an environment's JSON variable payload into map[string]any and returns this error when json.Unmarshal fails, meaning the stored environment JSON is not a syntactically valid JSON object. Environments store their variables as a JSON document, so any string that does not parse as an object is rejected by Validate.
Solutions
- Run the payload through a JSON linter or jq to fix syntax errors before sending it
- Ensure the payload is a JSON object ({...}), not an array or scalar
- Build the payload with a JSON encoder (jq, json.Marshal) instead of string concatenation
Example fix
// before
payload := "{VAR1: 'value1',}" // invalid JSON
// after
payload, _ := json.Marshal(map[string]any{"VAR1": "value1"}) Defensive patterns
Strategy: validation
Validate before calling
var probe map[string]any
if err := json.Unmarshal([]byte(payload), &probe); err != nil {
return fmt.Errorf("environment payload is not valid JSON: %w", err)
} Type guard
func isJSONObject(s string) bool {
var m map[string]any
return json.Unmarshal([]byte(s), &m) == nil
} Try / catch
if err := env.Validate(); err != nil {
if strings.Contains(err.Error(), "must be valid JSON") {
return fmt.Errorf("environment rejected: %w", err)
}
return err
} Prevention
- Generate payloads with json.Marshal or jq, never string concatenation
- Lint JSON payloads (jq .) before submitting environments
- Verify templating output is fully rendered and free of shell-quoting artifacts
When it happens
Trigger: Creating/updating an environment where the "json" field contains malformed JSON (trailing commas, unquoted keys, single quotes, truncated output from templating) or a valid JSON value that is not an object (array, string, number).
Common situations: Shell heredocs or jq -c output interpolated with unescaped quotes into the payload; CI scripts concatenating JSON strings manually; pasting YAML instead of JSON into an environment editor.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- key can not be empty
- values must be scalar
- missing secret
- invalid environment secret type
- secret must be valid json in key
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/a08f3d2fff5fe529.
Report an issue: GitHub.
Appendix: source
Thrown at db/Environment.go:89
return nil
}
if s.Secret == "" {
return errors.New("missing secret")
}
return errors.New("invalid environment secret type")
}
func validateJSON(s string, mustValuesBeScalar bool) error {
if s == "" {
return nil
}
var data map[string]any
err := json.Unmarshal([]byte(s), &data)
if err != nil {
return errors.New("must be valid JSON")
}
for k, v := range data {
if k == "" {
return errors.New("key can not be empty")
}
if mustValuesBeScalar {
switch v.(type) {
case []any, map[string]any:
return errors.New("values must be scalar")
}
}
}
return nil
}
View on GitHub (pinned to 1774ccb71a)