siyuan-note/siyuan · error
unsupported path type: %T
Error message
unsupported path type: %T
What it means
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.
Source
Thrown at kernel/plugin/sandbox.go:316
err = fmt.Errorf("path %v: value is %s", key, cursor.String())
return
}
obj := cursor.ToObject(rt)
if obj == nil {
err = fmt.Errorf("path %v: expected object, got %T", key, cursor)
return
}
switch k := key.(type) {
case string:
cursor = obj.Get(k)
path = fmt.Sprintf("%s.%s", path, k)
case int:
cursor = obj.Get(strconv.Itoa(k))
path = fmt.Sprintf("%s[%d]", path, k)
default:
err = fmt.Errorf("unsupported path type: %T", key)
return
}
}
value = cursor
return
}
// dispatchEvent calls the globalThis.siyuan.event.on hook with the given event object.
func dispatchEvent(p *KernelPlugin, rt *goja.Runtime, e any) (async bool, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("goja panic during dispatchEvent: %v", r)
}
}()
event, err := getJsContextValue(rt, []any{"siyuan", "event"})
if err != nil {
returnView on GitHub (pinned to 8641553a1f)
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
Example fix
// before
paths := []any{"siyuan", "server", scope, requestType} // scope is a custom int-typed enum
// after
paths := []any{"siyuan", "server", string(scope), string(requestType)} Defensive patterns
Strategy: type-guard
Validate before calling
func validPathSegments(paths []any) bool { for _, p := range paths { switch p.(type) { case string, int: default: return false } } return true } Type guard
func isPathSegment(k any) bool { switch k.(type) { case string, int: return true }; return false } Try / catch
if !validPathSegments(paths) { return fmt.Errorf("invalid path segments") }
value, err := getJsContextValue(rt, paths)
if err != nil { return err } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- injectServer: %v
- injectStorage: %v
- globalThis.siyuan.plugin.lifecycle is not an object
- path %v: expected object, got %T
- globalThis.siyuan.event is not an object
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/e99a6342cee85606.
Report an issue: GitHub.