Skip to content

Show a clear error when a connection's database driver isn't installed - #713

Merged
chrisclark merged 2 commits into
masterfrom
better-missing-driver-errors
Oct 5, 2026
Merged

chrisclark merged 2 commits into
masterfrom
better-missing-driver-errors

Conversation

@chrisclark

Copy link
Copy Markdown
Collaborator

Problem

A connection whose engine driver isn't installed (for example MySQL without mysqlclient) could be saved. After that, everything that touched it failed with a blank 500:

  • the schema pane, which shows a "sad page" icon because Django's 500 page sends X-Frame-Options: DENY inside the iframe
  • schema.json
  • Test connection
  • running queries

The cause: load_backend() raises ImproperlyConfigured, but as_django_connection() only caught DatabaseError. An unreachable database also 500'd the schema pane, because SchemaView didn't catch the OperationalError.

We found this on demo.sqlexplorer.io, where a visitor had added a MySQL connection.

Changes

  • Model: as_django_connection() turns a missing driver into a DatabaseError that names the package to install. The existing DatabaseError handling then shows it for query runs and Test connection.
  • Form: DatabaseConnectionForm refuses to save an engine whose driver can't be loaded, and labels those engines "(driver not installed)" in the dropdown. Test connection shows the specific message instead of "Invalid form data".
  • Schema pane: SchemaView renders the existing schema_error.html with the actual error, instead of a 500.
  • Schema JSON: schema_json_info() returns {} on failure. It used to return [], which made JsonResponse raise, so the existing InvalidExplorerConnectionException path also 500'd.

Testing

  • New tests cover the model, form, schema view, schema JSON and validate view.
  • Full suite: 284 tests pass under explorer.tests.settings and under settings_base (50 skipped). ruff==0.16.8 check explorer is clean.
  • End to end, against a real missing mysqlclient with no mocks:
    • the schema pane returns 200 with SAMEORIGIN and shows the install hint
    • schema.json returns {}
    • Test connection returns the message
    • saving the form is refused
    • the dropdown flags the 6 engines whose drivers aren't installed

🤖 Generated with Claude Code

chrisclark and others added 2 commits October 5, 2026 09:33
Previously, a connection whose engine driver wasn't installed (e.g. MySQL
without mysqlclient) could be saved, and then the schema pane, schema JSON,
"Test connection" and query runs all failed with a 500 because load_backend's
ImproperlyConfigured escaped. Unreachable databases had the same problem in the
schema pane.

- as_django_connection converts a missing driver into a DatabaseError that
  names the package to install, so existing DatabaseError handling shows it.
- The connection form refuses engines whose driver can't be loaded, and labels
  them "(driver not installed)" in the dropdown.
- The schema pane renders schema_error.html with the error instead of a 500.
- schema_json_info returns {} on failure (returning [] made JsonResponse raise).

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@chrisclark
chrisclark merged commit 1942422 into master Oct 5, 2026
11 checks passed
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.

1 participant