{"record":{"id":"e99a6342cee85606","repo":"siyuan-note/siyuan","slug":"unsupported-path-type-t","errorCode":null,"errorMessage":"unsupported path type: %T","messagePattern":"unsupported path type: %T","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/sandbox.go","lineNumber":316,"sourceCode":"\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)\n\t\t\treturn\n\t\t}\n\t}\n\tvalue = cursor\n\treturn\n}\n\n// dispatchEvent calls the globalThis.siyuan.event.on hook with the given event object.\nfunc dispatchEvent(p *KernelPlugin, rt *goja.Runtime, e any) (async bool, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"goja panic during dispatchEvent: %v\", r)\n\t\t}\n\t}()\n\n\tevent, err := getJsContextValue(rt, []any{\"siyuan\", \"event\"})\n\tif err != nil {\n\t\treturn","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/sandbox.go#L298-L334","documentation":"getJsContextValue walks a path of keys through the plugin's goja JS runtime starting at globalThis. Each path segment must be either a string (property name) or an int (converted to a string index). If a segment is any other Go type, the walk aborts with 'unsupported path type: %T'. This is a programming-error guard in the kernel, not a plugin-facing validation.","triggerScenarios":"A caller of getJsContextValue (e.g. dispatchEvent with [\"siyuan\",\"event\"], or getRequestHandler with [\"siyuan\",\"server\",scope,requestType]) passes a path element that is neither string nor int — e.g. a nil, float64, custom struct, or goja.Value segment.","commonSituations":"Kernel-side refactors where a path was built dynamically (e.g. fmt.Sprintf result used as a segment, or an enum typed as something other than string); new code reusing getJsContextValue for other lookups with untyped path slices.","solutions":["Inspect the caller's path slice and change the offending element to a string (or int for array indexes)","If the path is built dynamically, explicitly convert segments with fmt.Sprintf(\"%v\", seg) or a type switch before calling getJsContextValue","If it is your own kernel code, extend the switch in getJsContextValue to accept the new segment type instead of falling through to default"],"exampleFix":"// before\npaths := []any{\"siyuan\", \"server\", scope, requestType} // scope is a custom int-typed enum\n// after\npaths := []any{\"siyuan\", \"server\", string(scope), string(requestType)}","handlingStrategy":"type-guard","validationCode":"func validPathSegments(paths []any) bool { for _, p := range paths { switch p.(type) { case string, int: default: return false } } return true }","typeGuard":"func isPathSegment(k any) bool { switch k.(type) { case string, int: return true }; return false }","tryCatchPattern":"if !validPathSegments(paths) { return fmt.Errorf(\"invalid path segments\") }\nvalue, err := getJsContextValue(rt, paths)\nif err != nil { return err }","preventionTips":["Always build path slices with string literals or explicit casts (string(scope), string(requestType))","Add a unit test covering getJsContextValue with each path-segment type in use","Keep path slices as []string unless an array index is truly needed"],"tags":["goja","kernel","type-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}