Skip to content

Scripts and errors

QQL scripts are for repeatable provisioning, migrations, fixtures, and batched operations. Parse a script once, retain its statements, apply any trusted rewrite, and then plan or execute the result.

Statements are separated by one semicolon; a final semicolon is optional. Empty separators, adjacent unseparated statements, and scripts over 256 statements are rejected.

QQLProvision a catalog and query itTry in playground
CREATE COLLECTION catalog (dense VECTOR(384, COSINE));
CREATE INDEX ON COLLECTION catalog FOR category TYPE keyword;
UPSERT INTO catalog VALUES {id: 1, text: 'red chair', category: 'furniture'};
QUERY 'chair' FROM catalog USING dense LIMIT 5;

BATCH { ... } runs homogeneous same-collection members as one Qdrant batch RPC. Members are full statements: all queries or all mutations. Query batches carry shared read opts in PARAMS; mutation batches carry WAIT.

QQLOne RPC for same-collection membersTry in playground
BATCH { QUERY [0.1] FROM docs LIMIT 1; QUERY [0.2] FROM docs LIMIT 3; };
BATCH { QUERY [0.1] FROM docs LIMIT 1; QUERY [0.2] FROM docs LIMIT 3; } PARAMS (timeout = 30, consistency = majority);
BATCH { UPSERT INTO docs VALUES {id: 1, vector: [0.1]}; DELETE FROM docs WHERE id = 2; } WAIT false;

Empty blocks, nested blocks, mixed families, mixed collections, DDL, SHOW, COUNT, SCROLL, FACET, and SET QUOTA members fail closed. WAIT false sends ?wait=false explicitly. Edge fans out per member instead of sending a native batch RPC.

APIContract
Parser::parseOne complete statement only
Parser::parse_allOne complete semicolon-delimited script
SDK parseHost-language statement handles or objects
compile / explainOffline plan inspection
Executor or client executeOne statement, a script, or host array input

Host arrays are independent inputs. A semicolon-delimited script is one input that the runtime parses together, which matters when batching compatible operations.

Errors carry a stable code, kind, message, and optional zero-based UTF-8 byte span. Message text is not normative: match on the code. The stable codes are grouped by their prefix; see Error codes for the full list with meanings.

Code prefixFamilyExamples
QQL-LEX-*Lexical failuresQQL-LEX-STRING
QQL-PARSE-*Syntax, clause order, and value-range failuresQQL-PARSE-STATEMENT, QQL-PARSE-CLAUSE-ORDER, QQL-PARSE-DUPLICATE-KEY, QQL-PARSE-POSITIVE-INTEGER
QQL-VALIDATION-*Semantic validation of a parsed programQQL-VALIDATION-FROM, QQL-VALIDATION-UPSERT-ID, QQL-VALIDATION-SLICE, QQL-VALIDATION-IDF
QQL-PLAN-*, QQL-MISSING-*, QQL-UNKNOWN-*, QQL-VECTOR-KINDPlanning and schema resolutionQQL-PLAN-VECTOR-KIND, QQL-PLAN-QUOTA, QQL-PLAN-IDF, QQL-MISSING-USING
QQL-EMBEDDING-*UPSERT embedding inferenceQQL-EMBEDDING-TOPOLOGY, QQL-EMBEDDING-TARGET
QQL-EDGE-*In-process edge backend capability and runtime failuresQQL-EDGE-UNSUPPORTED-GROUP-LOOKUP, QQL-EDGE-UNSUPPORTED-QUOTA, QQL-EDGE-INVALID-POINT-ID
Transport / backendNetwork and Qdrant response failures during executionQQL-GRPC-QUOTA, other transport-layer QQL-*

A code already asserted by a v1 invalid fixture cannot change before v2. New codes may only refine previously unspecified cases.

SituationExample code familyWhat to do
Syntax or clause orderQQL-PARSE-*Show the span and preserve the user source
Missing required query structureQQL-VALIDATION-*Add the required FROM, PREFETCH, or valid parameter
Vector-role conflictQQL-PLAN-VECTOR-KINDAlign the query role with the collection topology
Service policy cannot be appliedpolicy errorReject the request rather than weakening the predicate

The Playground shows the same source, AST, compiled route, and explanation without connecting to Qdrant until you choose to run it.

Before deploying or committing scripts, use qql lint for static syntax, plan, and style verification:

Lint scripts offline
qql lint scripts/queries.qql qql lint --fix

qql lint is completely offline: it parses statements with error recovery, compiles them through the query planner, flags redundant WITH PAYLOAD true clauses, and checks canonical formatting without connecting to a cluster.

Live query triage with qql doctor / qql check

Section titled “Live query triage with qql doctor / qql check”

When troubleshooting live execution against a running cluster, run qql doctor "<statement>" (or qql check "<statement>"). It runs five stages in order and prints one line per stage with the QQL-* code on failure:

  1. Format check of the input.
  2. Offline explain (no backend needed).
  3. Embed endpoint dim probe when the statement needs text embeddings (skipped for literal-vector statements).
  4. USING and vector-name topology check against the live collection when reachable.
  5. Backend doctor (Qdrant reachability, with unreachable and auth failures reported distinctly).
Triage a statement against a live cluster
qql doctor "QUERY [0.1, 0.2, 0.3] FROM docs LIMIT 1" qql doctor "QUERY 'typed query language' FROM docs USING dense LIMIT 5"

Fix the first failing stage and rerun. Literal-vector statements pass the embed stage as skipped, so they are the fastest way to confirm the backend path is healthy.