{"record":{"id":"8363bdddd1496bef","repo":"weaviate/weaviate","slug":"sfield-must-be-a-string","errorCode":null,"errorMessage":"%sField must be a string","messagePattern":"(.+?)Field must be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"usecases/modulecomponents/settings/base_class_multimodal_settings.go","lineNumber":199,"sourceCode":"\t}\n\n\treturn nil\n}\n\nfunc (s *BaseClassMultiModalSettings) validateFields(name string, fields any) (int, error) {\n\tfieldsArray, ok := fields.([]any)\n\tif !ok {\n\t\treturn 0, fmt.Errorf(\"%sFields must be an array\", name)\n\t}\n\n\tif len(fieldsArray) == 0 {\n\t\treturn 0, fmt.Errorf(\"must contain at least one %s field name in %sFields\", name, name)\n\t}\n\n\tfor _, value := range fieldsArray {\n\t\tv, ok := value.(string)\n\t\tif !ok {\n\t\t\treturn 0, fmt.Errorf(\"%sField must be a string\", name)\n\t\t}\n\t\tif len(v) == 0 {\n\t\t\treturn 0, fmt.Errorf(\"%sField values cannot be empty\", name)\n\t\t}\n\t}\n\n\treturn len(fieldsArray), nil\n}\n\nfunc (s *BaseClassMultiModalSettings) validateWeights(name string, count int) error {\n\tweights, ok := s.getWeights(name)\n\tif ok {\n\t\tif len(weights) != count {\n\t\t\treturn fmt.Errorf(\"weights.%sFields does not equal number of %sFields\", name, name)\n\t\t}\n\t\t_, err := s.getWeightsArray(weights)\n\t\tif err != nil {\n\t\t\treturn err","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/usecases/modulecomponents/settings/base_class_multimodal_settings.go#L181-L217","documentation":"This error is thrown by validateFields when an entry in the configured %sFields array (e.g. imageFields/audioFields in a multimodal module config) is not a string. The module iterates over the JSON config array and asserts each element is a property-name string before accepting it.","triggerScenarios":"Setting multimodal module class config like {\"moduleConfig\":{\"multi2vec-clip\":{\"imageFields\":[{\"field\":\"blob\"}]}}} where elements are objects instead of strings, or mixing non-string values (numbers, null, nested arrays) into the fields array.","commonSituations":"Copying an older or wrong-module config example where fields were objects; generating config programmatically and serializing non-strings; hand-editing JSON and leaving a trailing object element.","solutions":["Change each element of the <name>Fields array to a plain string property name, e.g. \"imageFields\": [\"image\"] instead of [{\"field\":\"image\"}]","Print/validate the JSON config before applying it (jq 'map(type)' to check element types)","Check the specific module's documentation for the expected fields format"],"exampleFix":"// before\n\"moduleConfig\": {\"multi2vec-bind\": {\"imageFields\": [{\"field\": \"image\"}]}}\n// after\n\"moduleConfig\": {\"multi2vec-bind\": {\"imageFields\": [\"image\"]}}","handlingStrategy":"validation","validationCode":"const fields = cfg.imageFields || cfg.audioFields;\nif (!Array.isArray(fields) || fields.some(v => typeof v !== 'string')) {\n  throw new Error('each <name>Fields entry must be a string');\n}","typeGuard":"const isStringArray = (a: unknown): a is string[] => Array.isArray(a) && a.every(v => typeof v === 'string');","tryCatchPattern":null,"preventionTips":["Use the string-array form of fields arrays exactly as documented for the module","JSON-schema-validate moduleConfig before creating/updating classes","Never paste object-style field config from other modules"],"tags":["config-validation","multimodal","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}