{"record":{"id":"c4a2997b0ec8d2df","repo":"wavetermdev/waveterm","slug":"invalid-key-at-position-d-s","errorCode":null,"errorMessage":"invalid key at position %d: %s","messagePattern":"invalid key at position (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ijson/ijson.go","lineNumber":86,"sourceCode":"\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)\n\t\t\ti = j\n\t\t}\n\t\tif i < len(input) && input[i] == '.' {\n\t\t\ti++\n\t\t}\n\t}\n\n\treturn path, nil\n}\n\ntype PathError struct {\n\tErr string\n}\n\nfunc (e PathError) Error() string {\n\treturn \"PathError: \" + e.Err","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/ijson/ijson.go#L68-L104","documentation":"For non-bracket segments, ParseSimplePath extracts the key up to the next '.' or '[' and validates it against pathPartKeyRe (`^[a-zA-Z0-9:_#-]+`). Keys containing characters outside that set (dots inside keys, spaces, slashes, unicode, empty keys) fail with 'invalid key at position %d'. This keeps path strings unambiguous.","triggerScenarios":"Calling ParseSimplePath with a path containing a key with disallowed characters: \"my key\", \"a/b\", an empty segment like \"a..b\" (produces empty key), or leading non-matching characters (e.g. \".a\" at position 0 gives empty key).","commonSituations":"Map keys in the target JSON containing spaces, slashes, or punctuation; paths built by naive string concatenation producing double dots; localized/unicode key names.","solutions":["Rename the underlying JSON keys to match [a-zA-Z0-9:_#-], or","bypass ParseSimplePath and construct the Path slice directly as []any{\"my key\", 0} — Path is just an array of strings/ints.","Pre-sanitize input: split on '.' and '[' and reject segments not matching ^[a-zA-Z0-9:_#-]+$ before calling ParseSimplePath."],"exampleFix":"// before\npath, err := ijson.ParseSimplePath(\"user.full name\") // invalid key at position 5\n// after\npath := ijson.Path{\"user\", \"full name\"} // build Path directly for exotic keys\ndata, err := ijson.SetPath(doc, path, value, nil)","handlingStrategy":"validation","validationCode":"var pathPartRe = regexp.MustCompile(`^[a-zA-Z0-9:_#-]+$`)\nfor _, part := range strings.FieldsFunc(userPath, func(r rune) bool { return r == '.' || r == '[' }) {\n    part = strings.TrimSuffix(part, \"]\")\n    if !pathPartRe.MatchString(part) { return fmt.Errorf(\"invalid path key %q\", part) }\n}","typeGuard":null,"tryCatchPattern":"path, err := ijson.ParseSimplePath(input)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid key\") {\n        // fall back to constructing the Path slice directly\n        return fmt.Errorf(\"key contains unsupported characters: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep JSON map keys within [a-zA-Z0-9:_#-] so they are directly addressable.","For exotic keys, skip the string parser and build ijson.Path{...} literals directly.","Split-on-'.'/[' pre-checks catch empty segments (a..b) before ParseSimplePath does."],"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"}