# 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: ```text 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 under `diagnostics`. 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](job-refusals.md). The verdict ([verdicts.md](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). | | `Q129` | refused | A parameter (`input float`, `input angle`) a gradient cannot follow to the gates: under a modifier, in a classical variable, a condition, an index, a size, a loop's range, a subroutine or `gphase`, or one whose type rounds it (`angle[n]`, `float[32]`); a gradient follows a parameter through arithmetic, the built-in functions and gate definitions into a gate's arguments. | | `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. | | `Q453` | lowered | In a pulse run, a `cal` or `defcal` body read as OpenPulse and lowered to the schedule on frames (plays, delays, phase and frequency changes, captures and barriers) that the pulse simulator integrates. | | `Q454` | refused | In a pulse run, a `defcalgrammar` other than `"openpulse"`: the pulse reader reads OpenPulse alone. | | `Q455` | refused | A statement in a calibration that the pulse reader does not take: classical control, a frame's attributes or `get_phase`, an `extern` function, a frame made inside a `defcal`, a nested calibration, or a `defcal` over qubit arguments (the message names it and what to write instead). | | `Q456` | refused | A waveform that does not read: a template the reader does not know, arguments of the wrong number or kind, a length or a width that is not positive, a sample that is not a number, or more samples than it holds. | | `Q457` | refused | A frame or a port that does not read: a play, a delay or a phase or frequency change on a name that is not a frame, `newframe` on a name that is not a port, a frequency that is not a number, or a port that reaches no qubit. | | `Q458` | refused | A duration in a calibration that is not a whole, non-negative number of samples at the sample period (`dt`), or a schedule longer than the reader holds. | | `Q459` | refused | In a pulse run, a gate or a measurement on physical qubits that no `defcal` calibrates for those qubits and those parameters. | | `Q460` | refused | In a pulse run, a statement outside the calibrations that the pulse reader does not take: declared qubits (a pulse program names physical qubits, `$0`), a modifier, `reset`, classical control, a subroutine, or a measurement into something other than a bit. | | `Q461` | refused | A capture that does not read: not on a frame of an acquisition port, without a duration or a waveform, or its result put somewhere other than a bit. | | `Q462` | warned | A play on a measurement port: scheduled and timed, its effect on the readout not simulated (a capture reads the qubit's state). | | `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. | | `Q700` | refused | A file that does not read in the format named: QIR that is not LLVM text with one entry point, or jeff that is not a Cap'n Proto message of the jeff schema (a pointer outside the message, a struct or list of the wrong shape, more than the reader takes); the message says what and where. | | `Q701` | refused | A format version the reader does not take: QIR whose `qir_major_version` is not 1 or 2, or jeff other than 0.2 and 0.3. | | `Q702` | warned | A QIR module that leaves out what its profile requires (the `qir_profiles` attribute, the version flags, `required_num_qubits`, `required_num_results`, the `entry_point` attribute of its only function): read from what it holds, and said so. | | `Q703` | refused | A QIR profile the reader does not take: `qir_profiles` names neither `base_profile` nor `adaptive_profile`. | | `Q704` | refused | What the module's own QIR profile forbids: under the base profile a branch, a classical instruction, reading a result, or a gate or reset on a qubit after its measurement; under the adaptive profile an optional capability its module flags do not declare (computation on integers or floats of a type, IR-defined functions, loops, `switch`, several returns, dynamic qubits or results, arrays). | | `Q705` | refused | A QIR capability the module may use that this reader does not take: loops, `switch`, `phi`, IR-defined functions, dynamic allocation of qubits or results, arrays, controlled forms that take their controls in an array, or a classical value computed from a measurement anywhere but a branch's condition. | | `Q706` | refused | An instruction or function the reader does not know: a quantum intrinsic outside the gates it reads (`docs/formats.md` lists them), a runtime function it does not take, an LLVM instruction no profile lists, or a function a module declares and does not define. | | `Q707` | refused | A QIR operand that does not read: a qubit or result that is not a constant index, an index past `required_num_qubits` or `required_num_results`, or an angle that is not a finite number known on reading. | | `Q708` | refused | A value whose meaning the program's text cannot keep: in QIR a result read, measured again and only then branched on; in jeff a qubit the two sides of a branch on a measurement leave in different places. | | `Q709` | warned | Rotations at angles that are not dyadic multiples of 2π, read at their exact doubles: the double-precision methods take them; the bit-exact method refuses them (Q500). | | `Q710` | refused | A jeff custom gate the reader does not know: its name is not a gate of the standard library (in any case), or its qubits or parameters are not that gate's. | | `Q711` | warned | A jeff custom gate named as a gate of the standard library (`H`, `CX`, `Rx`, in any case) with that gate's qubits and parameters: read as that gate, by its name alone. | | `Q712` | lowered | A jeff Pauli-product rotation, `exp(iθP)` as its schema defines it, lowered exactly to basis changes, a parity ladder and one `rz`. | | `Q713` | refused | A jeff value used where it cannot be: a qubit or register used twice, a value used before it is defined or never defined, a cycle, or a value of the wrong type or count for its operation. | | `Q714` | refused | A jeff value the reader needs on reading and cannot know: a gate angle, a loop's bounds or a `while` condition from a measurement, a register's size or index, a `switch` on a value that is neither known nor a measured bit, or integer arithmetic on a measured bit beyond not, and, or, xor, eq and select. | | `Q715` | lowered | jeff's structured control flow: a `for` or `while` decided on reading unrolled, a `switch` on a known value decided, a `switch` on a measured bit written as `if … else`, and a call of a function the module defines inlined. | | `Q716` | warned | A jeff entry point that takes qubits: they are the program's first qubits, starting in \|0⟩, and the qubits it returns are not measured. | | `Q720` | refused | A program the format written cannot hold as it is: under QIR's base profile a measurement in the middle, a reset after a gate or a condition (write the adaptive profile), a loop in QIR, or in jeff a branch on a measured bit. | | `Q721` | warned | What the format read or written has no place for, left out and said so: delays, boxes, barriers and gate durations, calibrations, `output` declarations, and classical values recorded as output. | See `qasm-feature-matrix.md` for each construct of OpenQASM 3.1 and its code. The codes from `Q700` are those of the readers and writers of other formats (QIR and jeff, `formats.md`).