{"record":{"id":"a08f3d2fff5fe529","repo":"semaphoreui/semaphore","slug":"must-be-valid-json","errorCode":null,"errorMessage":"must be valid JSON","messagePattern":"must be valid JSON","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db/Environment.go","lineNumber":89,"sourceCode":"\t\treturn nil\n\t}\n\n\tif s.Secret == \"\" {\n\t\treturn errors.New(\"missing secret\")\n\t}\n\n\treturn errors.New(\"invalid environment secret type\")\n}\n\nfunc validateJSON(s string, mustValuesBeScalar bool) error {\n\tif s == \"\" {\n\t\treturn nil\n\t}\n\n\tvar data map[string]any\n\terr := json.Unmarshal([]byte(s), &data)\n\tif err != nil {\n\t\treturn errors.New(\"must be valid JSON\")\n\t}\n\n\tfor k, v := range data {\n\t\tif k == \"\" {\n\t\t\treturn errors.New(\"key can not be empty\")\n\t\t}\n\n\t\tif mustValuesBeScalar {\n\t\t\tswitch v.(type) {\n\t\t\tcase []any, map[string]any:\n\t\t\t\treturn errors.New(\"values must be scalar\")\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/db/Environment.go#L71-L107","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\npayload := \"{VAR1: 'value1',}\" // invalid JSON\n// after\npayload, _ := json.Marshal(map[string]any{\"VAR1\": \"value1\"})","handlingStrategy":"validation","validationCode":"var probe map[string]any\nif err := json.Unmarshal([]byte(payload), &probe); err != nil {\n\treturn fmt.Errorf(\"environment payload is not valid JSON: %w\", err)\n}","typeGuard":"func isJSONObject(s string) bool {\n\tvar m map[string]any\n\treturn json.Unmarshal([]byte(s), &m) == nil\n}","tryCatchPattern":"if err := env.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"must be valid JSON\") {\n\t\treturn fmt.Errorf(\"environment rejected: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["go","json","validation","environment"],"backgroundTag":"json-parse-error","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}