siyuan-note/siyuan · error

not found

Error message

%s not found

What it means

When mapping multipart form parts onto the request struct, a field typed *multipart.FileHeader (or a slice of them) must be present in form.File under its api tag name unless the tag includes ,optional,. If the named file part is absent, decoding fails with "<name> not found". It enforces required file uploads at the contract layer.

Solutions

  1. Append the file to FormData under the exact field name from the endpoint's request struct `api` tag.
  2. If the file is genuinely optional, mark the struct field's api tag as `api:"name,optional"`.
  3. Check server logs / the contract definition to confirm the expected field name, then align the client.

Example fix

// before
formData.append("upload", fileObj) // struct expects "file"
// after
formData.append("file", fileObj)
Defensive patterns

Strategy: validation

Validate before calling

function requireFile(formData, name) {
  const f = formData.get(name);
  if (f == null || typeof f === "string") throw new Error("file part '" + name + "' is required");
}

Type guard

const isUploadedFile = (v) => v != null && typeof v !== "string"; // File/Blob in browser

Try / catch

try { await upload(url, formData); } catch (e) { if (String(e).includes("not found")) { throw new Error("missing required file part — check field name matches the api tag"); } throw e; }

Prevention

When it happens

Trigger: POSTing to a multipart endpoint without appending a file under the exact field name declared by the struct's `api` tag (e.g. the struct requires "file" but the client sent "upload").

Common situations: Client uses a different form field name than the contract; file input left empty in the UI; contract changed the field name while the client still uses the old one.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at kernel/apicontract/multipart.go:73

		value.Set(reflect.ValueOf(MultipartFields{Value: form.Value, File: form.File}))
		return
	}
	if value.Kind() != reflect.Struct {
		return request, fmt.Errorf("multipart request must be a struct")
	}
	if err = validateMultipartRequest(value.Type()); err != nil {
		return
	}
	for i := 0; i < value.NumField(); i++ {
		field := value.Type().Field(i)
		name := strings.Split(field.Tag.Get("json"), ",")[0]
		optional := strings.Contains(","+field.Tag.Get("api")+",", ",optional,")
		switch field.Type {
		case reflect.TypeFor[*multipart.FileHeader](), reflect.TypeFor[[]*multipart.FileHeader]():
			files := form.File[name]
			if len(files) == 0 {
				if !optional {
					return request, fmt.Errorf("%s not found", name)
				}
				continue
			}
			if field.Type.Kind() == reflect.Slice {
				value.Field(i).Set(reflect.ValueOf(files))
			} else {
				value.Field(i).Set(reflect.ValueOf(files[0]))
			}
		case reflect.TypeFor[string](), reflect.TypeFor[*string]():
			values := form.Value[name]
			if len(values) == 0 {
				if !optional {
					return request, fmt.Errorf("Field [%s] is required", name)
				}
				continue
			}
			if field.Type.Kind() == reflect.Pointer {
				text := reflect.New(field.Type.Elem())

View on GitHub (pinned to 9f775e8a12)