Skip to content

Fix device.run() fails for QuantumCircuit subclasses (e.g. bound qiskit-nature UCCSD): "Alias 'qiskit' is already registered with a different type" - #1483

Open
DBVamsi wants to merge 3 commits into
qBraid:mainfrom
DBVamsi:fix/issue-1480
Open

DBVamsi wants to merge 3 commits into
qBraid:mainfrom
DBVamsi:fix/issue-1480

Conversation

@DBVamsi

@DBVamsi DBVamsi commented Oct 16, 2026

Copy link
Copy Markdown

Fixes #1480.

What changed

Summary

Root Cause

When QuantumDevice.run() is called with a QuantumCircuit subclass (e.g., qiskit-nature's UCCSD, TwoLocal, EfficientSU2), the code was using type(run_input) to create a ProgramSpec. Since get_program_type_alias() returns "qiskit" for any QuantumCircuit subclass (via isinstance), but ProgramSpec(type(run_input), alias="qiskit") tried to register the subclass under the "qiskit" alias, it collided with the already-registered QuantumCircuit type, raising:

ValueError: Alias 'qiskit' is already registered with a different type

Changes

1. qbraid/runtime/device.py (line ~466)

  • In apply_runtime_profile(): Changed from ProgramSpec(type(run_input), alias=run_input_alias) to ProgramSpec(QPROGRAM_REGISTRY[run_input_alias], alias=run_input_alias) when the alias is known.

2. qbraid/programs/program.py (line ~79)

  • In QuantumProgram.get_spec(): Same fix — use QPROGRAM_REGISTRY[alias] instead of type(program).

Test Added

Added TestQuantumCircuitSubclass class in tests/runtime/test_device.py with 3 tests:

  1. test_apply_runtime_profile_with_quantum_circuit_subclass — Verifies apply_runtime_profile() works with a custom QuantumCircuit subclass
  2. test_get_spec_with_subclass — Verifies QuantumProgram.get_spec() works with subclasses
  3. test_program_spec_from_subclass_uses_registered_type — Verifies the fix logic directly

How it was verified

  • test(s) added/changed: tests/runtime/test_device.py
  • on the original code the new test fails (exit 1)
  • with the fix it passes (exit 0)
  • full test suite with the fix: exit 1, no new failures vs. baseline (exit 1) (39.6s)

This was worked on in conjunction with AI tools.

…it-nature UCCSD): "Alias 'qiskit' is already registered with a different type"

Fixes qBraid#1480.
@argus-eye

argus-eye Bot commented Oct 16, 2026

Copy link
Copy Markdown

Argus review

Auto-review is off for this repo. Tick the box below to run a review on this PR.

  • Trigger Argus review

Estimated cost

  • Files changed: 3
  • Diff lines (±): 86
  • Historical avg: ~338.9k tokens · ~$0.81 · across last 20 review(s)

Tip: you can also comment @argus-eye review at any time.

@DBVamsi
DBVamsi requested a review from ryanhill1 as a code owner October 16, 2026 18:25
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: qBraid/qBraid/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ab6631e8-4b99-474f-b45e-2e8e6806517a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Document the QuantumCircuit subclass ProgramSpec fix and reorder the qbraid.programs import in device.py so QPROGRAM_REGISTRY comes first.
DBVamsi added a commit to DBVamsi/qBraid that referenced this pull request Oct 21, 2026
Resolve the CHANGELOG conflict by keeping the new qBraid#1490 and qBraid#1486 entries
alongside this PR's qBraid#1483 entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the CHANGELOG conflict by keeping the new qBraid#1490 and qBraid#1486 entries
alongside this PR's qBraid#1483 entry.

@ryanhill1 ryanhill1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix. The subclass case works, and the other two new tests fail if the production change is reverted. Two things to change before this merges, both inline.

Comment thread qbraid/runtime/device.py
if self._target_spec is not None and self._options.get("transpile") is True:
run_input_alias = get_program_type_alias(run_input, safe=True)
run_input_spec = ProgramSpec(type(run_input), alias=run_input_alias)
program_type = QPROGRAM_REGISTRY[run_input_alias] if run_input_alias else type(run_input)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QPROGRAM_REGISTRY[run_input_alias] raises a bare KeyError if the resolved alias has been unregistered. get_program_type_alias returns the metatype's alias (qasm2, qasm3, ionq, ...) without checking the registry, and unregister_program_type is public API. tests/transpiler/test_conversion_graph.py:521 calls it, for example.

Repro:

from qbraid.programs import QPROGRAM_REGISTRY, get_program_type_alias, unregister_program_type

unregister_program_type("qasm2")
alias = get_program_type_alias('OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[1];\nh q[0];\n')  # "qasm2"
QPROGRAM_REGISTRY[alias]  # KeyError: 'qasm2'

Before this PR, ProgramSpec(str, alias="qasm2") just re-registered the alias, so apply_runtime_profile on a QASM 2 string with transpile=True worked. Now it fails with a KeyError, which callers catching ProgramConversionError/ProgramTypeError won't handle. Falling back to the old behavior keeps the subclass fix:

Suggested change
program_type = QPROGRAM_REGISTRY[run_input_alias] if run_input_alias else type(run_input)
program_type = (
QPROGRAM_REGISTRY.get(run_input_alias, type(run_input))
if run_input_alias
else type(run_input)
)

The same expression is in qbraid/programs/program.py:79:

program_type = QPROGRAM_REGISTRY.get(alias, type(program)) if alias else type(program)

assert alias == "qiskit"

# The fix: use the registered type, not type(circuit)
program_type = QPROGRAM_REGISTRY[alias] if alias else type(circuit)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test copies the fix expression instead of calling the code it's meant to cover, so it still passes if the change in device.py or program.py is reverted. I checked: with both production changes reverted, the other two tests in this class fail and this one passes.

Calling get_spec makes it test the real path:

def test_program_spec_from_subclass_uses_registered_type(self):
    """get_spec on a subclass should record the registered parent type."""
    pytest.importorskip("qiskit", reason="qiskit not installed")
    from qiskit import QuantumCircuit

    from qbraid.programs.program import QuantumProgram

    class MyCircuit(QuantumCircuit):
        """Custom QuantumCircuit subclass."""

    spec = QuantumProgram.get_spec(MyCircuit(2))
    assert spec.program_type is QuantumCircuit
    assert spec.alias == "qiskit"

Or add assert spec.program_type is QuantumCircuit to test_get_spec_with_subclass, which currently checks only the alias, and drop this test.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

device.run() fails for QuantumCircuit subclasses (e.g. bound qiskit-nature UCCSD): "Alias 'qiskit' is already registered with a different type"

2 participants