siyuan-note/siyuan · error
globalThis.Object.freeze is not a function
Error message
globalThis.Object.freeze is not a function
What it means
ObjectFreeze resolves globalThis.Object and expects its "freeze" property to be a callable JS function. If Object exists but Object.freeze is not a function (e.g. it was overwritten with a non-function value), this error is thrown via goja.AssertFunction. It means the sandbox's Object built-in has been tampered with or stubbed incompletely.
Source
Thrown at kernel/plugin/sandbox.go:132
lo.Must0(injectServer(p, rt, siyuan))
lo.Must0(injectSecretsVars(p, rt, siyuan))
lo.Must0(ObjectFreeze(rt, siyuan))
lo.Must0(rt.GlobalObject().Set("siyuan", siyuan))
return
}
// ObjectFreeze calls Object.freeze() on the given goja object.
func ObjectFreeze(rt *goja.Runtime, obj *goja.Object) error {
Object := rt.GlobalObject().Get("Object").ToObject(rt)
if Object == nil {
return fmt.Errorf("globalThis.Object is not an object")
}
freeze, ok := goja.AssertFunction(Object.Get("freeze"))
if !ok {
return fmt.Errorf("globalThis.Object.freeze is not a function")
}
_, err := freeze(Object, obj)
return err
}
// ObjectSeal calls Object.seal() on the given goja object.
func ObjectSeal(rt *goja.Runtime, obj *goja.Object) error {
Object := rt.GlobalObject().Get("Object").ToObject(rt)
if Object == nil {
return fmt.Errorf("globalThis.Object is not an object")
}
seal, ok := goja.AssertFunction(Object.Get("seal"))
if !ok {
return fmt.Errorf("globalThis.Object.seal is not a function")
}
View on GitHub (pinned to 8641553a1f)
Solutions
- Restore or avoid overwriting globalThis.Object.freeze in runtime setup code
- Order operations so API objects are frozen before any untrusted plugin code runs
- If stubbing in tests, stub with a real function: globalThis.Object.freeze = (o) => o
- Wrap ObjectFreeze and fall back to skipping the freeze when the built-in is unusable
Example fix
// before
// test setup
rt.RunString("Object.freeze = 1")
plugin.ObjectFreeze(rt, obj) // error: not a function
// after
rt.RunString("const __f = Object.freeze; Object.freeze = (o) => __f(o)") Defensive patterns
Strategy: type-guard
Validate before calling
o := rt.GlobalObject().Get("Object")
if o != nil {
if _, ok := goja.AssertFunction(o.ToObject(rt).Get("freeze")); !ok { /* skip or restore */ }
} Type guard
func canFreeze(rt *goja.Runtime) bool {
o := rt.GlobalObject().Get("Object")
if o == nil { return false }
_, ok := goja.AssertFunction(o.ToObject(rt).Get("freeze"))
return ok
} Try / catch
if err := plugin.ObjectFreeze(rt, obj); err != nil {
logging.LogWarningf("freeze skipped: %v", err)
} Prevention
- Do not overwrite Object.freeze with non-function values (including in tests/polyfills)
- Freeze before untrusted code executes
- Stub with real functions when mocking
When it happens
Trigger: Calling ObjectFreeze on a runtime where globalThis.Object.freeze was reassigned to undefined, null, a plain value, or a non-callable proxy trap result — commonly after plugin code or a polyfill overwrote the built-in.
Common situations: A polyfill or shim that redefined Object without freeze; a security-hardened sandbox replacing freeze with a no-op plain function wrapper of wrong type; test code stubbing Object.freeze incorrectly before the runtime injected API objects.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- globalThis.Object is not an object
- globalThis.Object.seal is not a function
- RunScript: %v
- globalThis.siyuan.plugin.lifecycle not found
- globalThis.siyuan.plugin.lifecycle.%s not bound to a functio
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/64c0a5a371985038.
Report an issue: GitHub.