{"record":{"id":"1f12ef2f8f4176fd","repo":"semaphoreui/semaphore","slug":"invalid-default-value-must-be-string-or-string","errorCode":null,"errorMessage":"invalid default_value: must be string or []string","messagePattern":"invalid default_value: must be string or \\[\\]string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db/Template.go","lineNumber":118,"sourceCode":"\t}\n\n\t// try string\n\tvar s string\n\tif err := json.Unmarshal(b, &s); err == nil {\n\t\td.Values = []string{s}\n\t\td.originalWasArray = false\n\t\treturn nil\n\t}\n\n\t// try []string\n\tvar arr []string\n\tif err := json.Unmarshal(b, &arr); err == nil {\n\t\td.Values = arr\n\t\td.originalWasArray = true\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"invalid default_value: must be string or []string\")\n}\n\nfunc (d SurveyVarDefaultValue) MarshalJSON() ([]byte, error) {\n\tif d.Values == nil {\n\t\treturn []byte(\"null\"), nil\n\t}\n\tif len(d.Values) == 1 && !d.originalWasArray {\n\t\treturn json.Marshal(d.Values[0])\n\t}\n\treturn json.Marshal(d.Values)\n}\n\nfunc (d SurveyVarDefaultValue) String() string {\n\tif len(d.Values) == 0 {\n\t\treturn \"\"\n\t}\n\treturn d.Values[0]\n}","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/db/Template.go#L100-L136","documentation":"SurveyVarDefaultValue.UnmarshalJSON accepts either a JSON string or an array of strings for the default_value field. Any other JSON type (number, bool, object) produces 'invalid default_value: must be string or []string'. The custom unmarshaler also tracks whether the original value was an array.","triggerScenarios":"POST/PUT of a template whose survey variable default_value is a number, boolean, or nested object, e.g. {\"default_value\": 42} or {\"default_value\": {\"a\":1}}.","commonSituations":"API clients sending defaults for number/boolean survey vars without quoting them; UI forms submitting raw JS values; schema changes where defaults were previously untyped.","solutions":["Send the default_value as a JSON string, e.g. \"default_value\": \"42\" instead of 42","Send an array of strings for multi-value defaults, e.g. \"default_value\": [\"a\",\"b\"]","Fix the client/serializer to stringify non-string defaults before submitting the template"],"exampleFix":"// before\n{\"name\": \"count\", \"default_value\": 5}\n// after\n{\"name\": \"count\", \"default_value\": \"5\"}","handlingStrategy":"validation","validationCode":"func validDefaultValue(v any) bool {\n    switch t := v.(type) {\n    case string:\n        return true\n    case []any:\n        for _, e := range t {\n            if _, ok := e.(string); !ok { return false }\n        }\n        return true\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":"if err := json.Unmarshal(body, &tpl); err != nil {\n    if strings.Contains(err.Error(), \"invalid default_value\") {\n        http.Error(w, \"default_value must be a string or []string\", http.StatusBadRequest)\n        return\n    }\n    http.Error(w, err.Error(), http.StatusBadRequest)\n}","preventionTips":["Serialize survey defaults as strings or string arrays only","Stringify numbers/booleans on the client before submitting templates","Add JSON schema validation on template payloads"],"tags":["json","unmarshal","template"],"backgroundTag":"json-unmarshal-failed","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"}