{"record":{"id":"33a942f5eab9a226","repo":"siyuan-note/siyuan","slug":"path-required","errorCode":null,"errorMessage":"path required","messagePattern":"path required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_client.go","lineNumber":61,"sourceCode":"\t\t}\n\t}()\n\n\tclient := rt.NewObject()\n\n\tlo.Must0(client.Set(\"fetch\", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {\n\t\tpromise, resolve, reject := rt.NewPromise()\n\n\t\tvar argErr error\n\t\tvar path string\n\t\tmethod := \"GET\"\n\t\theaders := map[string]string{}\n\t\tvar bodyString *string\n\t\tvar bodyBytes *[]byte\n\n\t\tif goja.IsString(call.Argument(0)) {\n\t\t\tpath = call.Argument(0).String()\n\t\t} else {\n\t\t\targErr = fmt.Errorf(\"path required\")\n\t\t}\n\t\tif argErr == nil && !strings.HasPrefix(path, \"/\") {\n\t\t\targErr = fmt.Errorf(\"path must start with /\")\n\t\t}\n\t\tif argErr == nil {\n\t\t\tif init := call.Argument(1); isJsValueNotNull(init) {\n\t\t\t\tif initObj := init.ToObject(rt); initObj != nil {\n\t\t\t\t\tif m := initObj.Get(\"method\"); goja.IsString(m) {\n\t\t\t\t\t\tmethod = m.String()\n\t\t\t\t\t}\n\n\t\t\t\t\tif h := initObj.Get(\"headers\"); isJsValueNotNull(h) {\n\t\t\t\t\t\tif exportErr := rt.ExportTo(h, &headers); exportErr != nil {\n\t\t\t\t\t\t\targErr = fmt.Errorf(\"failed to export headers: %w\", exportErr)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif argErr == nil {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_client.go#L43-L79","documentation":"siyuan.client.fetch requires its first argument to be a string request path. When the argument is not a string (or missing/undefined), the bridge rejects the promise with \"path required\". The client only supports string-path requests like \"/api/...\".","triggerScenarios":"Calling siyuan.client.fetch() with no arguments, with a URL object, with an options object as the first argument (Node-fetch style: fetch({url:...})), or with null/undefined.","commonSituations":"Developers used to browser fetch({url}) or got/axios signatures pass a config object first; template variables interpolating to undefined.","solutions":["Pass the API path as a string first argument: siyuan.client.fetch(\"/api/...\", {method:\"POST\", ...})","If you have a URL object, pass url.pathname instead","Ensure the path variable is defined before the call","Coerce safely: if (typeof path === \"string\") await siyuan.client.fetch(path)"],"exampleFix":"// before\nawait siyuan.client.fetch({ url: \"/api/notebook/lsNotebooks\", method: \"GET\" })\n\n// after\nawait siyuan.client.fetch(\"/api/notebook/lsNotebooks\", { method: \"GET\" })","handlingStrategy":"validation","validationCode":"function assertPathArg(args) {\n  if (typeof args[0] !== \"string\") throw new TypeError(\"siyuan.client.fetch requires a string path as the first argument\");\n}","typeGuard":"const isFetchPath = (v) => typeof v === \"string\" && v.length > 0;","tryCatchPattern":"try {\n  const res = await siyuan.client.fetch(path, opts);\n} catch (e) {\n  if (String(e).includes(\"path required\")) {\n    console.error(\"fetch() first argument must be a string path, got:\", typeof path);\n  }\n}","preventionTips":["Always pass the path as the first string argument, options object second","Do not use fetch({url}) style signatures from other libraries","Check that interpolated path variables are defined"],"tags":["plugin","api","fetch","argument"],"backgroundTag":"missing-required-argument","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"}