{"record":{"id":"29ba78a3cd230a9d","repo":"siyuan-note/siyuan","slug":"no-file-found","errorCode":null,"errorMessage":"no file found","messagePattern":"no file found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/import.go","lineNumber":320,"sourceCode":"\tif len(token) != 32 {\n\t\treturn false\n\t}\n\tfor _, char := range token {\n\t\tif !(char >= 'a' && char <= 'z') && !(char >= 'A' && char <= 'Z') && !(char >= '0' && char <= '9') {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfunc saveImportUpload(c *gin.Context) (form *multipart.Form, writePath string, cleanup func(), err error) {\n\tform, err = c.MultipartForm()\n\tif err != nil {\n\t\treturn\n\t}\n\tfiles := form.File[\"file\"]\n\tif len(files) < 1 {\n\t\terr = errors.New(\"no file found\")\n\t\treturn\n\t}\n\n\timportDir := filepath.Join(util.TempDir, \"import\", gulu.Rand.String(7))\n\tif err = os.MkdirAll(importDir, 0755); err != nil {\n\t\treturn\n\t}\n\tcleanup = func() { _ = os.RemoveAll(importDir) }\n\twritePath = filepath.Join(importDir, filepath.Base(files[0].Filename))\n\tif !gulu.File.IsSubPath(importDir, writePath) {\n\t\terr = errors.New(\"import path is not sub path of import dir\")\n\t\tcleanup()\n\t\treturn\n\t}\n\n\tif err = c.SaveUploadedFile(files[0], writePath); err != nil {\n\t\tcleanup()\n\t}","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/api/import.go#L302-L338","documentation":"Returned by saveImportUpload (import.go:320) when the multipart form contained no entries under the 'file' field (len(form.File[\"file\"]) < 1). The import-upload handler requires at least one uploaded file part; an empty upload — wrong field name, empty form, or a client that forgot to attach the file — is rejected before any temp directory is created.","triggerScenarios":"POSTing to the import endpoint with a multipart form that omits the 'file' part, names it differently (e.g. 'data', 'upload'), or submits an empty file list. saveImportUpload at import.go:313 reads c.MultipartForm() then checks form.File[\"file\"] at line 318.","commonSituations":"Frontend/form field name mismatch ('file' vs 'files' vs a custom name). Curl invocation missing -F 'file=@...'. A proxy stripping form parts. Client sending JSON instead of multipart for this endpoint.","solutions":["Ensure the multipart request includes a part named exactly 'file' with a real file: curl -F 'file=@archive.zip' ...","Double-check the frontend FormData appends under the key 'file'.","Confirm Content-Type is multipart/form-data and the body was not emptied by a proxy or size limit."],"exampleFix":"// before\nconst fd = new FormData(); fd.append('upload', blob)\n// after\nconst fd = new FormData(); fd.append('file', blob)","handlingStrategy":"validation","validationCode":"// Ensure a 'file' part exists before submitting\nif (!fileBlob) { throw new Error('select a file to import'); }\nconst fd = new FormData(); fd.append('file', fileBlob);","typeGuard":null,"tryCatchPattern":"try { await importUpload(fd); }\ncatch (e) { if (/no file found/.test(e.msg)) { /* prompt user to attach file */ } else throw e; }","preventionTips":["Use the exact field name 'file' in the multipart form.","Require a non-empty file selection before enabling submit.","Verify Content-Type is multipart/form-data."],"tags":["import","upload","validation","kernel"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}