Skip to content

Report the real reason the C extension failed to load - #153

Merged
kesmit13 merged 1 commit into
mainfrom
fix-accel-import-diagnostic
Oct 29, 2026
Merged

kesmit13 merged 1 commit into
mainfrom
fix-accel-import-diagnostic

Conversation

@kesmit13

@kesmit13 kesmit13 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

When a connection is opened with pure_python=False and the C extension failed to import, Connection.__init__ retries the import only so it can print why, then raises NotSupportedError. The retry misspelled the module (_singlestortedb_accel), so stderr always showed:

ModuleNotFoundError: No module named '_singlestortedb_accel'

That hid the real loader error, such as a missing symbol, the wrong architecture or a too-old glibc. It only matters with an explicit pure_python=False; the default None falls back to pure Python without printing anything. But that is exactly what publish.yml's wheel tests use (?pure_python=0 in SINGLESTOREDB_URL), so a broken wheel in CI would have reported the wrong cause.

Why this isn't a one-letter fix

Correcting the spelling of the import statement breaks every connection. An import statement anywhere in __init__ makes _singlestoredb_accel local to the whole function, so the _singlestoredb_accel is None check before it and the elif _singlestoredb_accel is not None after it raise UnboundLocalError. The typo was avoiding that, most likely by accident. This retries with importlib.import_module('_singlestoredb_accel') instead, which doesn't bind any name.

Tests

singlestoredb/tests/test_accel_import.py; neither test needs a server:

  • test_reports_the_real_import_error makes the extension import fail with a specific ImportError by adding a finder to sys.meta_path, which an import statement and importlib both go through. It then checks that the error appears on stderr. It fails with the old typo.
  • test_loads_when_available builds a pure_python=False connection (defer_connect=True) while the extension is available and checks that the C result class is used. It fails with the one-letter fix, raising UnboundLocalError. It's skipped when the extension isn't built.

I ran it locally against a singlestoredb-dev container. test_basics.py, test_accel_leaks.py and the new tests pass, and test_basics.py plus the new tests also pass with SINGLESTOREDB_PURE_PYTHON=1. Pre-commit is clean.

🤖 Generated with Claude Code


Note

Low Risk
Narrow change to error reporting and import retry when pure_python=False; behavior for default connections is unchanged.

Overview
When pure_python=False and the C extension did not load at import time, Connection.__init__ retries the load only to print the failure to stderr before raising NotSupportedError. That retry used a misspelled module name (_singlestortedb_accel), so CI and users saw ModuleNotFoundError instead of the real loader error (e.g. missing GLIBC).

The fix loads _singlestoredb_accel via importlib.import_module, which retries the correct module without introducing a local binding that would break the existing _singlestoredb_accel is None checks in __init__ (a plain import there would cause UnboundLocalError on every connection).

Adds test_accel_import.py: one test asserts stderr contains a simulated import failure; another (when the extension is built) asserts pure_python=False still selects the C result class.

Reviewed by Cursor Bugbot for commit ce6c69c. Bugbot is set up for automated code reviews on this repo. Configure here.

With pure_python=False and a C extension that failed to import, the
connection retries the import only to print why, then raises
NotSupportedError. The retry misspelled the module name, so stderr always
showed "No module named '_singlestortedb_accel'" and hid the real loader
error (a missing symbol, wrong architecture, too-old glibc, ...).

Correcting the spelling in the import statement isn't enough: an import
statement in __init__ binds _singlestoredb_accel as a local for the whole
function, so the module-level checks before and after it raise
UnboundLocalError and every connection fails. The typo was avoiding
that. Retry with importlib.import_module instead, which binds nothing.

The new tests need no server. One makes the extension import fail and
checks that stderr carries that error; it fails with the old typo. The
other builds a pure_python=False connection while the extension is
available; it fails with the plain import-statement fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues are reported for the change improving C-extension import diagnostics.

No open issues 🎉

Review effort: Balanced

@kesmit13
kesmit13 merged commit a6f4247 into main Oct 29, 2026
15 of 16 checks passed
@kesmit13
kesmit13 deleted the fix-accel-import-diagnostic branch October 29, 2026 16:44

This branch was successfully deployed

1 active deployment
Base — ce6c69cc Deployed Oct 29, 2026 by kesmit13 via test-coverage #594
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.

2 participants