docs/verdicts.md gives the ladder, what a verdict records, the intents, the repair rules and every surface; the reader's diagnostics page points at the job layer's codes. The crate's, the command line's, the service's, the Python package's and the Studio's READMEs, and the changelog, describe them. Co-Authored-By: Claude Opus 5.5 <[email protected]>
12 KiB
OpenQASM reader: diagnostic codes
Every refusal and warning the reader gives (wai_quantum::qasm), and every
construct it lowers, carries or keeps verbatim, has a code. A refusal or a
warning reads, on every surface:
line 3: unknown gate foo [Q103]
and, as data (wai-quantum lint --json, the MCP servers' lint_qasm, the
job service, the Studio), carries its code, its outcome, its message
and where it stands: line, column and length, in characters.
Stability. A code never changes meaning once released. A construct that comes to be supported gets a new code for what now happens to it; the old code keeps its row, marked retired, so a code in an old log or receipt still means what it meant then. New codes are only ever added.
Outcomes.
refused: the program is not read, and nothing runs.lowered: read and lowered exactly to the engine's gates and steps.carried: kept in the program as written (its timing, its outputs), changing nothing a method computes unless the method says it uses it.preserved: kept verbatim for export, never executed.warned: read, with something the person should know; the job's result lists it underdiagnostics.
What is asked of a program (the request, the method, an intent, a repair,
the host) has codes of its own, J…: job-refusals.md.
The verdict (verdicts.md) carries a refusal's codes, and the
repair (wai-quantum repair, repair_qasm) makes the fixes that are
mechanical on the lines a diagnostic flags.
The table is also served as data: wai_quantum::qasm::diag::codes() in Rust,
wai-quantum diagnostics [--json] on the command line, the qasm_diagnostics
tool of both MCP servers, and engine_diagnostic_codes() in the browser
engine. A test holds this page to the code's table.
| Code | Outcome | Meaning |
|---|---|---|
Q001 |
refused | A character that is not part of the language. |
Q002 |
refused | A number that does not read: a malformed literal, or one too large to hold. |
Q003 |
refused | A string, a block comment, a bracket or a calibration block that is not closed. |
Q004 |
refused | Something else was expected here: a ;, a name, an expression or a statement (the message says which). |
Q005 |
refused | A statement in a place the language does not allow it: else with no if, case outside switch, a declaration inside a gate. |
Q010 |
warned | An OPENQASM version other than 2.x or 3.x: the program is read as OpenQASM 3. |
Q011 |
warned | An include of a file other than the standard libraries (stdgates.inc, qelib1.inc): its definitions are not read, so a gate it defines is unknown. |
Q012 |
lowered | include "stdgates.inc" or "qelib1.inc": the standard gates, U, gphase and OpenQASM 2's names are built in. |
Q013 |
warned | A pragma or annotation the reader does not act on: kept, not applied. |
Q100 |
refused | The program declares no qubits. |
Q101 |
refused | A name declared twice in one scope, or given to two kinds of thing (a register and an integer). |
Q102 |
refused | A name that is not declared: a register, a variable, an alias or a subroutine. |
Q103 |
refused | A gate that is neither in the standard library nor defined in the program. |
Q104 |
refused | A gate or subroutine given the wrong number of parameters, qubits or arguments. |
Q105 |
refused | A declaration only the top level may make (qubits, a gate, a subroutine, an extern) inside a block. |
Q106 |
refused | A word of the language, or a built-in constant (pi, tau, euler), used as a name. |
Q107 |
refused | An index or slice outside its register or array. |
Q108 |
refused | Registers of different lengths in one statement that applies to whole registers. |
Q109 |
refused | One qubit named twice in one gate. |
Q110 |
refused | A value of the wrong type here: a float where an integer is needed, a complex gate parameter, a qubit where a value is needed. |
Q111 |
refused | More qubits than the reader takes (65 536). |
Q112 |
refused | An integer outside its type's range (a negative uint, a value too wide for int[n]), or integer arithmetic that overflows. |
Q113 |
refused | Division, or a remainder, by zero. |
Q114 |
refused | An input given no value, or a value given for an input the program does not declare. |
Q115 |
refused | An input of a type the reader takes no value for: only int and uint inputs are given values. |
Q116 |
refused | A value that depends on a measurement used where the reader needs it on reading: a gate parameter, an index, a size, a loop's range. |
Q117 |
refused | A gate parameter that is not a finite number. |
Q118 |
refused | Integers divided with a remainder where a real number is wanted: OpenQASM 3 truncates 1/2 to 0 and OpenQASM 2 reads it as 0.5, so write 1.0/2. |
Q119 |
refused | ^ between integers in a program that does not say OPENQASM 3: OpenQASM 3 reads it as exclusive or, OpenQASM 2 as a power; write ** for a power. |
Q120 |
warned | ^ between real numbers, read as a power as OpenQASM 2 reads it; OpenQASM 3 writes **. |
Q121 |
warned | A value rounded to its declared width, as the language defines (angle[n] to n bits of a turn, float[32] and float[16] to single and half precision); the message gives the amount. |
Q122 |
refused | A type width the reader does not hold: a float other than float[16], float[32] and float[64], an integer or an angle wider than 64 bits. |
Q123 |
refused | A cast the language does not allow, or one whose value does not fit. |
Q124 |
refused | Physical qubits ($0) in a program that also declares qubits. |
Q125 |
refused | A call of an extern function, whose body is outside the program. |
Q126 |
refused | A call of an opaque gate, or of a gate with only a calibration: its matrix is not known. |
Q127 |
refused | An assignment to a constant, an input or a loop variable. |
Q128 |
refused | A measurement where a value is needed that is not a bit (measurement gives bits, into a bit register). |
Q200 |
lowered | A gate the program defines, inlined at each call with its parameters bound. |
Q201 |
lowered | ctrl @ and negctrl @ on any gate, lowered exactly to standard gates (a negative control is a control between two x). |
Q202 |
lowered | inv @ on any gate, user gates included: each gate's exact inverse, in reverse order. |
Q203 |
lowered | pow(k) @ with an integer k: angles scaled, or the gate repeated; a negative k repeats the inverse. |
Q204 |
lowered | pow(r) @ with a fractional r where an exact gate exists: the principal power (pow(1/2) @ x is sx, pow(r) @ rz(θ) is rz(rθ) for |θ| < 2π). |
Q205 |
refused | pow(r) @ with a fractional r where no exact gate exists here: a user gate, u, cu, or a rotation by 2π or more. |
Q206 |
lowered | gphase(θ): a global phase, which no measurement sees, dropped; under controls it is a phase on the controls. |
Q207 |
refused | A control modifier that adds no control: ctrl(0) @. |
Q208 |
refused | Modifiers that add more controls than the reader lowers (16). |
Q209 |
refused | Gate definitions or subroutine calls nested deeper than 32. |
Q210 |
refused | A program that expands to more gates than the reader holds (2 000 000). |
Q211 |
refused | A modifier on something that is not a gate. |
Q212 |
refused | A statement a gate's body may not hold: a gate holds gate calls, gphase, barrier, loops and conditions known on reading. |
Q300 |
lowered | An if, while or switch whose condition is known on reading: decided then. |
Q301 |
lowered | A condition on measured bits (c[0], c == 3, c >= 2, &&, ||, !), compiled to steps that branch on them. |
Q302 |
refused | A condition that reads neither measured bits nor values known on reading. |
Q303 |
refused | A bit register of more than one bit used as a condition: compare it with a number, as c == 3. |
Q304 |
refused | A comparison with a number that does not fit in the bits compared. |
Q305 |
refused | A negated operand compared with == or != (!c == 1): write c != 1. |
Q306 |
refused | Classical arithmetic on measured bits at run time, beyond a condition, or a comparison between two measured values: the program's steps branch on bits and hold no other run-time values. |
Q307 |
refused | A condition that reads more than 64 bits. |
Q308 |
lowered | for over a range, a set or an array: unrolled, once per value. |
Q309 |
lowered | while whose condition is known on reading: unrolled until it fails. |
Q310 |
refused | A while whose condition reads measured bits and that declares no bound: add @wai.max_iterations N before it. |
Q311 |
warned | A while on measured bits run at most its declared bound (@wai.max_iterations N): a run that still meets its condition after N iterations stops looping there. |
Q312 |
refused | A program that does not finish unrolling within the reader's bound (20 000 000 statements and loop iterations). |
Q313 |
refused | A range with a zero step, or that does not read as [start:end] or [start:step:end]. |
Q314 |
refused | break or continue outside a loop, or return outside a subroutine. |
Q315 |
refused | A return with a value under a condition on measured bits. |
Q316 |
lowered | break, continue, return and end: under a condition on measured bits, a jump forward in the steps. |
Q317 |
lowered | switch: decided on reading, or a chain of conditions on measured bits. |
Q318 |
lowered | A def subroutine, inlined at each call: classical arguments by value, qubits by reference, its return value given back. |
Q319 |
refused | A bit given anything but a measurement at run time: bits are written by measurement (a declaration may give them 0). |
Q320 |
refused | A measurement whose result goes nowhere: measure q; while bit registers are declared (write c = measure q;). |
Q321 |
refused | Qubits measured into a different number of bits. |
Q322 |
lowered | A bit declared inside a block or a subroutine: a bit of its own, which the steps read and the results do not show. |
Q400 |
warned | The method applies no durations: the program's delays, boxes and stretches change nothing it computes, and the result says so. |
Q401 |
carried | delay[d] on qubits, carried in the program's timing. |
Q402 |
carried | box (with or without a duration), carried in the timing around the gates it holds. |
Q403 |
carried | stretch: a duration a scheduler would solve, carried by name. |
Q404 |
carried | barrier, carried in the timing; it changes no gate. |
Q405 |
refused | durationof(…): it needs gate durations, which the program does not give the reader. |
Q406 |
refused | A duration that does not read: no unit, negative, or not known on reading. |
Q407 |
carried | A gate's duration (x[20ns] q;), carried in the timing, not applied. |
Q450 |
preserved | defcal: kept verbatim for export, never executed; the gate's matrix comes from its gate definition or the standard library. |
Q451 |
preserved | cal { … }: kept verbatim for export, never executed. |
Q452 |
preserved | defcalgrammar: kept verbatim for export. |
Q500 |
refused | An angle that is not a dyadic multiple of 2π (2πm/2^k, k ≤ 32): the bit-exact method refuses it, never rounds it; the methods in double precision take it. |
Q501 |
refused | More than 255 qubits for the bit-exact circuit. |
Q502 |
refused | A program that measures a qubit and then acts on it, resets one after its first gate, or acts on measured bits: the bit-exact circuit takes programs whose measurements all come at the end. |
Q600 |
carried | An output declaration, carried into the result: its bits (their places in each outcome) or its value. |
Q601 |
refused | An output that is not a bit and whose value depends on a measurement at the end. |
See qasm-feature-matrix.md for each construct of OpenQASM 3.1 and its code.