siyuan-note/siyuan · error
dom is required
Error message
dom is required
What it means
decodeExtensionCopyForm parses the multipart form of the extension copy endpoint (web clipper style) and requires a non-empty "dom" field; if form.Value["dom"] is empty it returns "dom is required". The endpoint copies editor content built from the submitted DOM string, so without it there is nothing to convert to Markdown.
Solutions
- Add a "dom" field to your multipart FormData containing the serialized DOM/content
- Verify the field name is exactly "dom" and it is sent as a form value part
- Use the official siyuan-chrome clipper request format as a reference
- Send the request as multipart/form-data, not JSON
Example fix
// before
formData.append("html", domString);
// after
formData.append("dom", domString); Defensive patterns
Strategy: validation
Validate before calling
function assertDomForm(formData) {
const dom = formData.get("dom");
if (!dom || typeof dom !== "string" || dom.length === 0) throw new Error("dom is required");
}
assertDomForm(formData); Type guard
const hasDomField = (fd) => typeof fd.get === "function" && typeof fd.get("dom") === "string" && fd.get("dom").length > 0; Try / catch
try { await clipCopy(formData); } catch (e) { if (String(e).includes("dom is required")) console.error("Multipart body missing dom field"); } Prevention
- Always append the "dom" part to your multipart FormData
- Match the official siyuan-chrome clipper field names
- Send multipart/form-data, not JSON, to extension endpoints
- Log FormData entries in development to verify parts
When it happens
Trigger: POSTing to the extension copy API via DecodeMultipart without a "dom" part in the multipart/form-data body, or with the field named incorrectly (e.g. "html", "content").
Common situations: Browser-extension or scraping integrations building FormData manually and forgetting the dom field; renamed form fields after upstream clipper updates; requests sent as JSON instead of multipart.
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
- endpoint does not accept multipart data
- Field [ ] is required
- Field [ ] is required
- Access to encrypted notebook data is not supported via this…
- AI editor action must not be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/738954a4765e129a.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/extension.go:24
)
type ExtensionCopyRequest struct {
DOM string `json:"dom"`
Notebook *string `json:"notebook" api:"optional"`
Href *string `json:"href" api:"optional"`
ClipType *string `json:"clipType" api:"optional"`
Assets *string `json:"assets" api:"optional"`
Files map[string][]*multipart.FileHeader `json:"-"`
}
type ExtensionCopyData struct {
Markdown string `json:"md"`
WithMath bool `json:"withMath"`
}
func decodeExtensionCopyForm(form *multipart.Form) (ExtensionCopyRequest, error) {
if len(form.Value["dom"]) == 0 {
return ExtensionCopyRequest{}, fmt.Errorf("dom is required")
}
first := func(name string) *string {
if values := form.Value[name]; len(values) > 0 {
return &values[0]
}
return nil
}
return ExtensionCopyRequest{DOM: form.Value["dom"][0], Notebook: first("notebook"), Href: first("href"),
ClipType: first("clipType"), Assets: first("assets"), Files: form.File}, nil
}
func extensionCopyRequestSchema() *Schema {
result := object(map[string]*Schema{"dom": {Type: "string"}, "notebook": {Type: "string"},
"href": {Type: "string"}, "clipType": {Type: "string"}, "assets": {Type: "string"}}, "dom")
// 资源字段名由剪藏页面的 URL 决定;同名上传文件和文本仍保留表单的重复值。
field := &Schema{AnyOf: []*Schema{{Type: "string"}, {Type: "string", Format: "binary"}}}
result.AdditionalProperties = &Schema{AnyOf: []*Schema{field, {Type: "array", Items: field}}}
return resultView on GitHub (pinned to 9f775e8a12)