antonmedv/fx · error

<error from goja Object.Set> (panic(err))

Error message

<error from goja Object.Set> (panic(err))

What it means

After unquoting the key, ToValue calls goja's obj.Set(unquotedKey, value). goja returns an error if the property cannot be set — e.g. a key equal to a non-writable built-in like '__proto__' or a symbol-like/invalid property name on a non-extensible object — and this code panics with that error. It converts a JS-engine property-set failure into a Go panic.

Source

Thrown at internal/jsonx/to_value.go:63

		obj := vm.NewObject()

		if n.HasChildren() {
			it := n
			if it.IsCollapsed() {
				it = it.Collapsed
			} else {
				it = it.Next
			}

			for it != nil && it != n.End {
				unquotedKey, err := utils.Unquote(it.Key)
				if err != nil {
					panic(err)
				}

				err = obj.Set(unquotedKey, it.ToValue(vm))
				if err != nil {
					panic(err)
				}

				if it.HasChildren() {
					it = it.End.Next
				} else {
					it = it.Next
				}
			}
		}

		return obj

	case Array:
		var arr []any

		if n.HasChildren() {
			it := n
			if it.IsCollapsed() {

View on GitHub (pinned to 4f31cd3a0c)

Solutions

  1. Rename or drop the '__proto__' key in the input before conversion.
  2. Sanitize untrusted JSON: reject or strip dangerous keys like __proto__, constructor, prototype.
  3. Pre-process the object with a filter that skips un-settable keys, or build the goja object with DefineData/own map instead.
  4. Recover the panic upstream and report the offending key.

Example fix

// before
{"__proto__": {"admin": true}, "a": 1}
// after
{"prototype": {"admin": true}, "a": 1} // or remove the key entirely
Defensive patterns

Strategy: validation

Validate before calling

func hasUnsafeKeys(data []byte) bool {
    var m map[string]json.RawMessage
    if json.Unmarshal(data, &m) != nil {
        return true
    }
    for k := range m {
        if k == "__proto__" || k == "constructor" || k == "prototype" {
            return true
        }
    }
    return false
}

Try / catch

func safeToValue(n *jsonx.Node, vm *goja.Runtime) (v goja.Value, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("cannot set property on goja object: %v", r)
        }
    }()
    return n.ToValue(vm), nil
}

Prevention

When it happens

Trigger: Converting an Object node containing the key '__proto__' (goja rejects setting it directly via Set) or otherwise unwritable property names, during ToValue/KeysComplete.

Common situations: JSON documents crafted with "__proto__" keys (prototype-pollution payloads, e.g. from untrusted web input), or keys colliding with engine internals.

Related errors


AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02). Data as JSON: /api/errors/b4e110e28c7ac388. Report an issue: GitHub.