siyuan-note/siyuan · error

Field [ ] must not be empty

Error message

Field [%s] must not be empty

What it means

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.

Solutions

  1. Send only string elements in packageNames, e.g. ["siyuan-plugin-a","siyuan-plugin-b"]
  2. Filter out null/undefined values before serializing the array on the client
  3. Check request.NamesError / the API error response to see the decode result
  4. Validate the payload shape against the generated API contract schema

Example fix

// before
fetchPost('/api/bazaar/getBazaarPackageRatings', {packageType: 'plugins', packageNames: [null, 'x']})
// after
fetchPost('/api/bazaar/getBazaarPackageRatings', {packageType: 'plugins', packageNames: ['x']})
Defensive patterns

Strategy: validation

Validate before calling

function validatePackageNames(names) {
    return Array.isArray(names) && names.every(n => typeof n === 'string') && names.length > 0;
}
// call before the API
if (!validatePackageNames(packageNames)) throw new Error('packageNames must be a non-empty array of strings');

Type guard

const isStringArray = (v) => Array.isArray(v) && v.every(n => typeof n === 'string');

Try / catch

try {
    await fetchPost('/api/bazaar/getBazaarPackageRatings', {packageType, packageNames: names.filter(n => typeof n === 'string')});
} catch (e) {
    console.error('invalid packageNames payload:', e.message);
}

Prevention

When it happens

Trigger: Calling /api/bazaar/getBazaarPackageRatings or getBazaarPackageUserRatings with packageNames containing null, a number (e.g. [1,2]), nested objects, or booleans.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/7de3fe8078042be3. Report an issue: GitHub.

Appendix: source

Thrown at kernel/apicontract/bazaar.go:464

		s, err := b.schema(member, input)
		if err != nil {
			return nil, err
		}
		variants = append(variants, s)
	}
	b.definitions[t.Name()] = &Schema{AnyOf: variants}
	return &Schema{Ref: "#/$defs/" + t.Name()}, nil
}

func bazaarString(fields map[string]json.RawMessage, key string, required, trim bool) (string, error) {
	value, err := legacyField[string](fields, key, "String", required)
	if err != nil {
		return "", err
	}
	if trim && len(fields[key]) > 0 && string(fields[key]) != "null" {
		value = strings.TrimSpace(value)
		if value == "" {
			return "", fmt.Errorf("Field [%s] must not be empty", key)
		}
	}
	return value, nil
}
func init() {
	InstallLocalBazaarPackage.decodeFailure = func(err error) Response[BazaarLocalInstallResult] {
		return Failure[BazaarLocalInstallResult](1, "Marketplace package file is required")
	}
	BatchUpdatePackage.decodeRequest = func(reader io.Reader) (request BatchUpdatePackageRequest, err error) {
		fields, err := bazaarRequestFields(reader, "/api/bazaar/batchUpdatePackage")
		if err != nil {
			return request, err
		}
		if request.Frontend, err = bazaarString(fields, "frontend", true, true); err != nil {
			return request, err
		}
		return request, nil
	}

View on GitHub (pinned to 9f775e8a12)