{"record":{"id":"7de3fe8078042be3","repo":"siyuan-note/siyuan","slug":"field-s-must-not-be-empty-bazaar","errorCode":null,"errorMessage":"Field [%s] must not be empty","messagePattern":"Field \\[(.+?)\\] must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/apicontract/bazaar.go","lineNumber":464,"sourceCode":"\t\ts, err := b.schema(member, input)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvariants = append(variants, s)\n\t}\n\tb.definitions[t.Name()] = &Schema{AnyOf: variants}\n\treturn &Schema{Ref: \"#/$defs/\" + t.Name()}, nil\n}\n\nfunc bazaarString(fields map[string]json.RawMessage, key string, required, trim bool) (string, error) {\n\tvalue, err := legacyField[string](fields, key, \"String\", required)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif trim && len(fields[key]) > 0 && string(fields[key]) != \"null\" {\n\t\tvalue = strings.TrimSpace(value)\n\t\tif value == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"Field [%s] must not be empty\", key)\n\t\t}\n\t}\n\treturn value, nil\n}\nfunc init() {\n\tInstallLocalBazaarPackage.decodeFailure = func(err error) Response[BazaarLocalInstallResult] {\n\t\treturn Failure[BazaarLocalInstallResult](1, \"Marketplace package file is required\")\n\t}\n\tBatchUpdatePackage.decodeRequest = func(reader io.Reader) (request BatchUpdatePackageRequest, err error) {\n\t\tfields, err := bazaarRequestFields(reader, \"/api/bazaar/batchUpdatePackage\")\n\t\tif err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\tif request.Frontend, err = bazaarString(fields, \"frontend\", true, true); err != nil {\n\t\t\treturn request, err\n\t\t}\n\t\treturn request, nil\n\t}","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/apicontract/bazaar.go#L446-L482","documentation":"When decoding getBazaarPackageRatings/getBazaarPackageUserRatings requests, each packageNames element is unmarshaled into a string; JSON null or a non-string element (number, object, bool) causes the decoder to record this error on the request instead of failing outright, preserving legacy response behavior. It signals the packageNames array is present but not an array of strings.","triggerScenarios":"Calling /api/bazaar/getBazaarPackageRatings or getBazaarPackageUserRatings with packageNames containing null, a number (e.g. [1,2]), nested objects, or booleans.","commonSituations":"Client code builds the array from mixed-type data; a null slips in from an undefined variable serialized by JSON.stringify; external API consumers guess the schema.","solutions":["Send only string elements in packageNames, e.g. [\"siyuan-plugin-a\",\"siyuan-plugin-b\"]","Filter out null/undefined values before serializing the array on the client","Check request.NamesError / the API error response to see the decode result","Validate the payload shape against the generated API contract schema"],"exampleFix":"// before\nfetchPost('/api/bazaar/getBazaarPackageRatings', {packageType: 'plugins', packageNames: [null, 'x']})\n// after\nfetchPost('/api/bazaar/getBazaarPackageRatings', {packageType: 'plugins', packageNames: ['x']})","handlingStrategy":"validation","validationCode":"function validatePackageNames(names) {\n    return Array.isArray(names) && names.every(n => typeof n === 'string') && names.length > 0;\n}\n// call before the API\nif (!validatePackageNames(packageNames)) throw new Error('packageNames must be a non-empty array of strings');","typeGuard":"const isStringArray = (v) => Array.isArray(v) && v.every(n => typeof n === 'string');","tryCatchPattern":"try {\n    await fetchPost('/api/bazaar/getBazaarPackageRatings', {packageType, packageNames: names.filter(n => typeof n === 'string')});\n} catch (e) {\n    console.error('invalid packageNames payload:', e.message);\n}","preventionTips":["Filter null/undefined/non-strings out of packageNames before serialization","Type-check request builders so packageNames is string[] end to end","Validate payloads against the generated API contract schema in tests"],"tags":["api","validation","json","bazaar","request"],"backgroundTag":"schema-validation-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}