ImportError: cannot import name 'ElasticsearchException' from 'elasticsearch'" after elasticsearch-py 8 upgrade
Fixes ImportError: cannot import name 'ElasticsearchException' from 'elasticsearch' after upgrading to elasticsearch-py 8. Use it when exception imports or except clauses break on the 8.x client. Key trigger: version 8 reorganized exceptions into elasticsearch.exceptions with ApiError and TransportError as the bases, so ElasticsearchException must be replaced with the specific exception classes.
TL;DR: elasticsearch-py 8 removed the old ElasticsearchException catch-all. Import the specific exceptions from elasticsearch.exceptions instead: ApiError for API failures, TransportError for connection-level failures, and NotFoundError for missing documents. Update both the imports and the except clauses, then rerun the failing paths.
The error
"ImportError: cannot import name 'ElasticsearchException' from 'elasticsearch'" after elasticsearch-py 8 upgradeSteps to fix
Find the breakage: search the codebase for ElasticsearchException in imports and except clauses. Expected: You have every site that referenced the removed name.
Replace the import: from elasticsearch.exceptions import ApiError, TransportError, NotFoundError (pick the ones you catch). Expected: The import succeeds on elasticsearch-py 8.
Rewrite except clauses: except ElasticsearchException becomes except ApiError for API errors, except TransportError for transport errors. Expected: Exception handling compiles and catches the intended failures.
Check the client construction too: the 8.x client takes hosts as a list and request_timeout instead of the old timeout kwarg. Expected: Client instantiation works without deprecation errors.
Run the integration tests against a real or containerized Elasticsearch 8. Expected: Tests pass with the new exception hierarchy.
Use this when
- elasticsearch-py 8 upgrade breaks with cannot import name 'ElasticsearchException'
- except clauses referencing the old exception hierarchy fail after the bump
- An agent upgraded the elasticsearch client and needs the exception mapping
Not for this skill when
- Connection failures to the cluster itself, which are network or auth problems
- Query DSL errors returned by Elasticsearch, which are request problems
- Version 7 client issues, where ElasticsearchException still exists
Variant phrasings
- elasticsearch 8 exceptions module
- ElasticsearchException removed in elasticsearch-py 8
- ApiError vs ElasticsearchException migration
Why it happens
The 7.x client exposed a single ElasticsearchException base that everything inherited from, which made it easy to catch too broadly. Version 8 rebuilt the exception hierarchy around ApiError (the server answered with an error) and TransportError (the request never completed), with specific subclasses like NotFoundError. The old name was deleted rather than aliased so that overly broad except clauses would fail loudly instead of silently changing meaning.
Edge cases
- Catching ApiError is still broad; prefer NotFoundError or ConflictError where you know the case you handle.
- The 8.x client is stricter about TLS and auth by default; exception fixes can reveal a second wave of connection-config changes.
- If you support both 7.x and 8.x, branch the import with a try/except ImportError fallback rather than pinning one major.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_2-7jfQ9JRDApWKZwl0WkgA