{"record":{"id":"c3466ec13c093746","repo":"siyuan-note/siyuan","slug":"path-v-value-is-s","errorCode":null,"errorMessage":"path %v: value is %s","messagePattern":"path (.+?): value is (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/sandbox.go","lineNumber":298,"sourceCode":"\tif err := ObjectSetDataMethods(p, rt, obj, data); err != nil {\n\t\treturn nil, err\n\t}\n\treturn obj, nil\n}\n\n// getJsContextValue safely retrieves a nested value from the plugin's JS context, returning nil if any step fails.\nfunc getJsContextValue(rt *goja.Runtime, paths []any) (value goja.Value, err error) {\n\tvar cursor goja.Value = rt.GlobalObject()\n\tvar path string = \"globalThis\"\n\n\tfor _, key := range paths {\n\t\tif cursor == nil {\n\t\t\terr = fmt.Errorf(\"path %v: value is nil\", key)\n\t\t\treturn\n\t\t}\n\n\t\tif goja.IsUndefined(cursor) || goja.IsNull(cursor) {\n\t\t\terr = fmt.Errorf(\"path %v: value is %s\", key, cursor.String())\n\t\t\treturn\n\t\t}\n\n\t\tobj := cursor.ToObject(rt)\n\t\tif obj == nil {\n\t\t\terr = fmt.Errorf(\"path %v: expected object, got %T\", key, cursor)\n\t\t\treturn\n\t\t}\n\n\t\tswitch k := key.(type) {\n\t\tcase string:\n\t\t\tcursor = obj.Get(k)\n\t\t\tpath = fmt.Sprintf(\"%s.%s\", path, k)\n\t\tcase int:\n\t\t\tcursor = obj.Get(strconv.Itoa(k))\n\t\t\tpath = fmt.Sprintf(\"%s[%d]\", path, k)\n\t\tdefault:\n\t\t\terr = fmt.Errorf(\"unsupported path type: %T\", key)","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/sandbox.go#L280-L316","documentation":"getJsContextValue traverses a property path from globalThis and rejects undefined/null intermediates because they cannot be dereferenced further. When the cursor at some key is undefined or null, this error reports the key and its string form (\"undefined\" or \"null\"). It means the requested path points through a property that does not exist in the runtime's global context.","triggerScenarios":"Calling getJsContextValue with a path containing a missing property — e.g. obj.Get(k) returned undefined for a key, or a namespace like siyuan.agent was never injected, and a later hop tries to traverse it.","commonSituations":"Event or request dispatch referencing an API that a plugin version doesn't provide; renamed API endpoints between kernel versions; dynamic path construction from user/plugin input containing invalid segments.","solutions":["Confirm the full path exists in the runtime (check with rt.GlobalObject().Get on each segment)","Update the plugin or kernel so both sides agree on the API path","Validate dispatch/request paths against the known siyuan API surface before resolving","Treat the error as 'API not present in this runtime' and degrade the caller gracefully"],"exampleFix":"// before\ngetJsContextValue(rt, []any{\"siyuan\", \"rpc\", \"oldMethod\"}) // error: path oldMethod: value is undefined\n// after\nv, err := getJsContextValue(rt, []any{\"siyuan\", \"rpc\", \"oldMethod\"})\nif err != nil {\n    logging.LogWarnf(\"api not available: %v\", err)\n    return\n}","handlingStrategy":"validation","validationCode":"v, err := getJsContextValue(rt, paths)\nif err != nil || v == nil || goja.IsUndefined(v) || goja.IsNull(v) {\n    // API not present in this runtime; degrade\n}","typeGuard":null,"tryCatchPattern":"v, err := getJsContextValue(rt, paths)\nif err != nil {\n    logging.LogWarnf(\"api unavailable: %v\", err)\n    return\n}","preventionTips":["Keep kernel and plugin API surface versions aligned","Validate dispatch/request paths against known API names","Treat undefined paths as optional features and degrade gracefully"],"tags":["goja","context-path","undefined","plugin-sandbox"],"backgroundTag":"resource-not-found","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}