cayleygraph/cayley · error
too many close parentheses at char %d: %s
Error message
too many close parentheses at char %d: %s
What it means
The s-expression parser for query languages tracks parenthesis depth while scanning input. If a ')' appears when parenDepth is already 0, the input is malformed, so Parse returns this error with the character offset and a snippet of the input up to that point.
Source
Thrown at query/sexp/session.go:62
func NewSession(qs graph.QuadStore) *Session {
return &Session{qs: qs}
}
func (s *Session) Parse(input string) error {
var parenDepth int
for i, x := range input {
if x == '(' {
parenDepth++
}
if x == ')' {
parenDepth--
if parenDepth < 0 {
min := 0
if (i - 10) > min {
min = i - 10
}
return fmt.Errorf("too many close parentheses at char %d: %s", i, input[min:i])
}
}
}
if parenDepth > 0 {
return query.ErrParseMore
}
if len(ParseString(input)) > 0 {
return nil
}
return errors.New("invalid syntax")
}
func (s *Session) Execute(ctx context.Context, input string, opt query.Options) (query.Iterator, error) {
switch opt.Collation {
case query.Raw, query.REPL:
default:
return nil, &query.ErrUnsupportedCollation{Collation: opt.Collation}
}View on GitHub (pinned to 81dcd7d73e)
Solutions
- Count parens in the query and remove the extra ')' indicated by the char offset in the message.
- Parse incrementally / build queries with a helper that balances parens.
- If input may legitimately be incomplete, check for query.ErrParseMore semantics and feed more input instead.
Example fix
// before q := "(start))" // after q := "(start)"
Defensive patterns
Strategy: validation
Validate before calling
func balanced(s string) bool {
d := 0
for _, r := range s {
if r == '(' { d++ } else if r == ')' { d-- }
if d < 0 { return false }
}
return d == 0
}
if !balanced(q) { /* fix input before Parse */ } Type guard
func isBalancedSexp(s string) bool { d := 0; for _, r := range s { if r == '(' { d++ }; if r == ')' { d-- }; if d < 0 { return false } }; return d == 0 } Try / catch
it, err := sess.Parse(q)
if err != nil {
if errors.Is(err, query.ErrParseMore) { /* feed more input */ }
if strings.Contains(err.Error(), "too many close parentheses") {
// parse offset from message, repair input
}
return err
} Prevention
- Build s-expressions with a writer that tracks paren depth.
- Lint queries for balanced parens before sending.
- Avoid hand-editing generated s-expression queries.
When it happens
Trigger: Calling Parse (query/sexp/session.go) on a query string containing more ')' than '(' before it, e.g. ":a))" or an unbalanced template-generated expression.
Common situations: Hand-written s-expression queries; programmatic query builders that append extra closing parens; copy-paste errors that drop an opening paren.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid syntax
- ErrParseMore
- wrong quad tag format: '%s'
- cannot count iterator without a valid context
- node tokens not valid
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/17812644fde97bc4.
Report an issue: GitHub.