wavetermdev/waveterm · error

unmatched bracket at position %d

Error message

unmatched bracket at position %d

What it means

ParseSimplePath parses ijson path strings like 'a.b[0].c'. When it encounters '[', it searches for the closing ']' with strings.Index; if none exists anywhere in the remaining input, it returns 'unmatched bracket at position %d'. The path string is malformed and nothing is parsed.

Source

Thrown at pkg/ijson/ijson.go:70

func MakeAppendCommand(path Path, value any) Command {
	return Command{
		"type": AppendCommandStr,
		"path": path,
		"data": value,
	}
}

var pathPartKeyRe = regexp.MustCompile(`^[a-zA-Z0-9:_#-]+`)

func ParseSimplePath(input string) ([]any, error) {
	var path []any
	// Scan the input string character by character
	for i := 0; i < len(input); {
		if input[i] == '[' {
			// Handle the index
			end := strings.Index(input[i:], "]")
			if end == -1 {
				return nil, fmt.Errorf("unmatched bracket at position %d", i)
			}
			index, err := strconv.Atoi(input[i+1 : i+end])
			if err != nil {
				return nil, fmt.Errorf("invalid index at position %d: %v", i, err)
			}
			path = append(path, index)
			i += end + 1
		} else {
			// Handle the key
			j := i
			for j < len(input) && input[j] != '.' && input[j] != '[' {
				j++
			}
			key := input[i:j]
			if !pathPartKeyRe.MatchString(key) {
				return nil, fmt.Errorf("invalid key at position %d: %s", i, key)
			}
			path = append(path, key)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Validate/complete the bracket syntax in the input string before calling ParseSimplePath.
  2. Reject the path at the input boundary and surface a user-facing message about unbalanced brackets.
  3. If paths come from templates, fix the template so index syntax is `key[<int>]`.

Example fix

// before
path, err := ijson.ParseSimplePath("window[0") // unmatched bracket at position 6
// after
func validateSimplePath(s string) error {
    depth := 0
    for _, r := range s {
        if r == '[' { depth++ } else if r == ']' { depth--; if depth < 0 { return errors.New("extra ]") } }
    }
    if depth != 0 { return errors.New("unbalanced brackets") }
    return nil
}
if err := validateSimplePath("window[0]"); err != nil { return err }
path, err := ijson.ParseSimplePath("window[0]")
Defensive patterns

Strategy: validation

Validate before calling

func hasBalancedBrackets(s string) bool {
    depth := 0
    for _, r := range s {
        if r == '[' { depth++ } else if r == ']' { depth--; if depth < 0 { return false } }
    }
    return depth == 0
}
if !hasBalancedBrackets(userPath) { return errors.New("unbalanced brackets in path") }

Try / catch

path, err := ijson.ParseSimplePath(input)
if err != nil {
    return fmt.Errorf("invalid path %q: %w", input, err) // surface position to user
}

Prevention

When it happens

Trigger: Calling ParseSimplePath (directly, or indirectly with a user-supplied path string) with input containing '[' but no subsequent ']' — e.g. "users[0" or "a[".

Common situations: Path strings typed by users in a UI/CLI and passed unvalidated; string interpolation that dropped the closing bracket; truncation of a path during logging or templating.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/58bd581954d50bb5. Report an issue: GitHub.