{"record":{"id":"70efe2d878e8fc41","repo":"siyuan-note/siyuan","slug":"panic-during-siyuan-client-fetch-v","errorCode":null,"errorMessage":"panic during siyuan.client.fetch: %v","messagePattern":"panic during siyuan\\.client\\.fetch: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_client.go","lineNumber":106,"sourceCode":"\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunErr := p.worker.Run(func(rt *goja.Runtime) (_ any, err error) {\n\t\t\tif argErr != nil {\n\t\t\t\terr = argErr\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tgo func() {\n\t\t\t\tvar err error\n\t\t\t\tdefer func() {\n\t\t\t\t\tif r := recover(); r != nil {\n\t\t\t\t\t\terr = fmt.Errorf(\"panic during siyuan.client.fetch: %v\", r)\n\t\t\t\t\t}\n\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tp.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {\n\t\t\t\t\t\t\tif rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {\n\t\t\t\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.client.fetch reject: %v\", p.Name, rejectErr)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}, nil)\n\t\t\t\t\t}\n\t\t\t\t}()\n\n\t\t\t\ttargetURL := fmt.Sprintf(\"http://127.0.0.1:%s%s\", util.ServerPort, path)\n\t\t\t\tr := httpClient.R()\n\t\t\t\tfor k, v := range headers {\n\t\t\t\t\tr.SetHeader(k, v)\n\t\t\t\t}\n\t\t\t\tr.SetHeader(model.XAuthTokenKey, p.token)","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_client.go#L88-L124","documentation":"A panic was recovered inside the background goroutine that performs the HTTP request for siyuan.client.fetch. The %v is the recovered panic value. This is an internal failure (nil pointer, slice out of range, etc.) in the request path, not a caller argument error — argument errors are caught earlier and reject with their own message.","triggerScenarios":"A bug in the kernel plugin runtime or a dependency panicking during request construction, send, or response assembly; or the plugin being unloaded (context cancelled) mid-request racing with response building.","commonSituations":"Kernel/plugin version mismatch, plugin hot-reload while a fetch is in flight, or an unhandled nil from httpClient.R(). Rare in normal use.","solutions":["Check the kernel log for the panic stack (the message includes the recovered value) and report it with the plugin name.","Ensure the plugin is not being unloaded/reloaded while requests are in flight.","Update to the latest kernel/plugin version — panics are usually fixed bugs."],"exampleFix":"try {\n  await siyuan.client.fetch('/api/x');\n} catch (e) {\n  // internal panic, not an argument error — log and degrade\n  console.error('fetch panic', e);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const res = await siyuan.client.fetch('/api/x');\n} catch (e) {\n  if (String(e).startsWith('panic during')) {\n    // internal runtime failure — log; optionally retry once\n  } else {\n    // argument or network error — handle by message\n  }\n}","preventionTips":["Always await fetch inside try/catch in plugins.","Avoid unloading/reloading a plugin while it has pending requests.","Keep kernel and plugin runtime versions in sync."],"tags":["client-fetch","panic","internal","concurrency"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}