wavetermdev/waveterm · error
invalid key at position %d: %s
Error message
invalid key at position %d: %s
What it means
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.
Source
Thrown at pkg/ijson/ijson.go:86
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)
i = j
}
if i < len(input) && input[i] == '.' {
i++
}
}
return path, nil
}
type PathError struct {
Err string
}
func (e PathError) Error() string {
return "PathError: " + e.ErrView on GitHub (pinned to a4447c1563)
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.
Example fix
// before
path, err := ijson.ParseSimplePath("user.full name") // invalid key at position 5
// after
path := ijson.Path{"user", "full name"} // build Path directly for exotic keys
data, err := ijson.SetPath(doc, path, value, nil) Defensive patterns
Strategy: validation
Validate before calling
var pathPartRe = regexp.MustCompile(`^[a-zA-Z0-9:_#-]+$`)
for _, part := range strings.FieldsFunc(userPath, func(r rune) bool { return r == '.' || r == '[' }) {
part = strings.TrimSuffix(part, "]")
if !pathPartRe.MatchString(part) { return fmt.Errorf("invalid path key %q", part) }
} Try / catch
path, err := ijson.ParseSimplePath(input)
if err != nil {
if strings.Contains(err.Error(), "invalid key") {
// fall back to constructing the Path slice directly
return fmt.Errorf("key contains unsupported characters: %w", err)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: Map keys in the target JSON containing spaces, slashes, or punctuation; paths built by naive string concatenation producing double dots; localized/unicode key names.
Related errors
- unmatched bracket at position %d
- invalid index at position %d: %v
- backup metadata mismatch: expected %s, got %s
- invalid format of user@host argument
- invalid object reference: %q
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/c4a2997b0ec8d2df.
Report an issue: GitHub.