Skip to content

Bug: Lexer error in v25.3.0: Unexpected character while lexing DQL: U+003C '<' when query starts with IRI-ref #9666

@eileenaaa

Description

@eileenaaa

Describe the bug

After upgrading from Dgraph v24.1.2 to v25.3.0, DQL queries using angle-bracket-wrapped names (e.g. <caseNodeDel_xxx>) as the first token after { fail with:

Unexpected character while lexing DQL: U+003C '<'

This is a regression introduced by commit 6c31f0475 ("Add implementation for RunDQL for v25 #9355"). In v24, lexTopLevel routed { directly to lexQuery, which supports < (IRI-ref style names). In v25, the new lexIdentifyMutationOrQuery state function was inserted between lexTopLevel and lexQuery to distinguish mutations (set/delete) from queries, but it does not handle the < character, causing the lexer to reject valid DQL.

To Reproduce

Steps to reproduce the behavior:

  1. Deploy Dgraph v25.3.0
  2. Send the following DQL query:
{
  <caseNodeDel_xxx> as var(func: eq(caseXid, "xxx")) @filter(type(Case))

  check(func: uid(caseNodeDel_xxx)) {
    uid
    caseXid
  }
}
  1. Observe error response:
{
  "errors": [
    {
      "message": "while lexing {\n\n  <caseNodeDel_xxx> as var(func: eq(caseXid, \"xxx\")) @filter(type(Case))\n\n  check(func: uid(caseNodeDel_xxx)) {\n    uid\n    caseXid\n\n  }\n\n} at line 3 column 2: Unexpected character while lexing DQL: U+003C '<'",
      "extensions": {
        "code": "ErrorInvalidRequest"
      }
    }
  ]
}

Expected behavior

The query should execute without lexing errors, as it did in v24.1.2. Supporting the syntax is necessary to avoid breaking existing DQL workflows that rely on IRI-ref style naming to handle special characters or to maintain RDF-standard compatibility.

Environment

  • OS: Windows
  • Language: Go
  • Version: v25.3.0 (worked correctly in v24.1.2)

Additional context

Root Cause

In dql/state.go, commit 6c31f0475 changed lexTopLevel to route { to the new lexIdentifyMutationOrQuery instead of directly to lexQuery. The new function handles isNameBegin characters (to detect set/delete/del for mutations vs query names) but omits the case r == lsThan branch, so < falls through to the default error case.

Proposed Fix

Add a case r == lsThan branch in lexIdentifyMutationOrQuery (dql/state.go) that parses the IRI ref and then transitions to lexQuery:

case r == lsThan:
    if err := lex.IRIRef(l, itemName); err != nil {
        return l.Errorf(err.Error())
    }
    return lexQuery

The proposed fix ensures that when the lexer encounters a < at the start of a block, it correctly identifies it as the start of an IRI-ref and proceeds to parse it as a query, maintaining the same behavior as v24.

Detailed fix implementation can be reviewed in this pr:
#9667

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions