cayleygraph/cayley · error

too many close parentheses at char

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.

Solutions

  1. Count parens in the query and remove the extra ')' indicated by the char offset in the message.
  2. Parse incrementally / build queries with a helper that balances parens.
  3. 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

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


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/17812644fde97bc4. Report an issue: GitHub.

Appendix: 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)