{"record":{"id":"58bd581954d50bb5","repo":"wavetermdev/waveterm","slug":"unmatched-bracket-at-position-d","errorCode":null,"errorMessage":"unmatched bracket at position %d","messagePattern":"unmatched bracket at position (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ijson/ijson.go","lineNumber":70,"sourceCode":"func MakeAppendCommand(path Path, value any) Command {\n\treturn Command{\n\t\t\"type\": AppendCommandStr,\n\t\t\"path\": path,\n\t\t\"data\": value,\n\t}\n}\n\nvar pathPartKeyRe = regexp.MustCompile(`^[a-zA-Z0-9:_#-]+`)\n\nfunc ParseSimplePath(input string) ([]any, error) {\n\tvar path []any\n\t// Scan the input string character by character\n\tfor i := 0; i < len(input); {\n\t\tif input[i] == '[' {\n\t\t\t// Handle the index\n\t\t\tend := strings.Index(input[i:], \"]\")\n\t\t\tif end == -1 {\n\t\t\t\treturn nil, fmt.Errorf(\"unmatched bracket at position %d\", i)\n\t\t\t}\n\t\t\tindex, err := strconv.Atoi(input[i+1 : i+end])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid index at position %d: %v\", i, err)\n\t\t\t}\n\t\t\tpath = append(path, index)\n\t\t\ti += end + 1\n\t\t} else {\n\t\t\t// Handle the key\n\t\t\tj := i\n\t\t\tfor j < len(input) && input[j] != '.' && input[j] != '[' {\n\t\t\t\tj++\n\t\t\t}\n\t\t\tkey := input[i:j]\n\t\t\tif !pathPartKeyRe.MatchString(key) {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid key at position %d: %s\", i, key)\n\t\t\t}\n\t\t\tpath = append(path, key)","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/ijson/ijson.go#L52-L88","documentation":"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.","triggerScenarios":"Calling ParseSimplePath (directly, or indirectly with a user-supplied path string) with input containing '[' but no subsequent ']' — e.g. \"users[0\" or \"a[\".","commonSituations":"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.","solutions":["Validate/complete the bracket syntax in the input string before calling ParseSimplePath.","Reject the path at the input boundary and surface a user-facing message about unbalanced brackets.","If paths come from templates, fix the template so index syntax is `key[<int>]`."],"exampleFix":"// before\npath, err := ijson.ParseSimplePath(\"window[0\") // unmatched bracket at position 6\n// after\nfunc validateSimplePath(s string) error {\n    depth := 0\n    for _, r := range s {\n        if r == '[' { depth++ } else if r == ']' { depth--; if depth < 0 { return errors.New(\"extra ]\") } }\n    }\n    if depth != 0 { return errors.New(\"unbalanced brackets\") }\n    return nil\n}\nif err := validateSimplePath(\"window[0]\"); err != nil { return err }\npath, err := ijson.ParseSimplePath(\"window[0]\")","handlingStrategy":"validation","validationCode":"func hasBalancedBrackets(s string) bool {\n    depth := 0\n    for _, r := range s {\n        if r == '[' { depth++ } else if r == ']' { depth--; if depth < 0 { return false } }\n    }\n    return depth == 0\n}\nif !hasBalancedBrackets(userPath) { return errors.New(\"unbalanced brackets in path\") }","typeGuard":null,"tryCatchPattern":"path, err := ijson.ParseSimplePath(input)\nif err != nil {\n    return fmt.Errorf(\"invalid path %q: %w\", input, err) // surface position to user\n}","preventionTips":["Validate path syntax at the input boundary with a regex like ^\\w+(\\.\\w+|\\[\\d+\\])*$ .","Escape or reject user-supplied strings that may contain '[' before treating them as paths.","Never build path strings by concatenation of untrusted fragments; use ijson.Path slices directly when the structure is known."],"tags":["parsing","path","validation"],"backgroundTag":"path-parse-error","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}