antonmedv/fx · error

<error from utils.Unquote(n.Value) unquoting the string node

Error message

<error from utils.Unquote(n.Value) unquoting the string node> (panic(err))

What it means

For String nodes, ToValue calls utils.Unquote to turn the raw token text (including quotes and escape sequences) into the unquoted Go string. If Unquote fails — the token contains an invalid escape sequence or malformed quoting — the error is panicked. This means a String node holds text that is not a well-formed JSON string literal.

Source

Thrown at internal/jsonx/to_value.go:40

		} else {
			return vm.ToValue(false)
		}

	case Number:
		i, ok := ParseNumber(n.Value)
		if ok {
			return vm.ToValue(i)
		}
		f, err := strconv.ParseFloat(n.Value, 64)
		if err == nil {
			return vm.ToValue(f)
		}
		panic(err)

	case String:
		unquoted, err := utils.Unquote(n.Value)
		if err != nil {
			panic(err)
		}
		return vm.ToValue(unquoted)

	case Object:
		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)

View on GitHub (pinned to 4f31cd3a0c)

Solutions

  1. Fix the string literal so all backslashes are properly escaped (\\) and quotes/escapes are JSON-valid.
  2. Re-parse the source document rather than constructing String nodes manually.
  3. Validate with a JSON linter before parsing; escape backslashes programmatically when generating input.
  4. Recover the panic and surface it with the node's line number for debugging.

Example fix

// before
{"path": "C:\Users\x"}
// after
{"path": "C:\\Users\\x"}
Defensive patterns

Strategy: type-guard

Validate before calling

var s string
if err := json.Unmarshal([]byte(n.Value), &s); err != nil {
    return fmt.Errorf("string node %q is not a valid JSON string", n.Value)
}

Type guard

func isValidStringNode(n *jsonx.Node) bool {
    if n.Kind != jsonx.String {
        return false
    }
    var s string
    return json.Unmarshal([]byte(n.Value), &s) == nil
}

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("ToValue failed on string node: %v", r)
        }
    }()
    return n.ToValue(vm), nil
}

Prevention

When it happens

Trigger: ToValue on a String node whose Value has bad escapes (e.g. '\x41', lone backslash, raw control characters) or is missing/malformed surrounding quotes — typically from hand-built nodes or corrupted input.

Common situations: Windows paths with single backslashes pasted into JSON ("C:\Users\x"), hand-constructed nodes in tests, files edited with tools that mangle escapes.

Related errors


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