ErrLookup › Background articles › Python NotImplementedError: when a method, backend, or platform is deliberately unsupported

Python NotImplementedError: when a method, backend, or platform is deliberately unsupported

NotImplementedError is the signal Python libraries raise when a method exists on a type but does no real work in the current context. Developers meet it when they subclass a base class without overriding an abstract method, ask a database or result backend for a feature it structurally lacks, run on a platform missing a stdlib dependency, or push an unsupported node through a restricted query grammar. It is almost never a bug to patch around; it is a contract or capability boundary, and the fix is to choose a different method, backend, subclass, or platform rather than to force the call through.

Distilled from 198 documented records across 19 repositories.

Background

NotImplementedError is a built-in Python exception that libraries raise to mark a method that is present on a type's interface but performs no real work in this context. Unlike AttributeError, which means the attribute does not exist, NotImplementedError means the author knew about the call and deliberately declined it here. In the libraries studied, it is the standard mechanism for four related but distinct boundaries: abstract base classes enforcing an override contract, backends declining features they cannot support, restricted grammars rejecting operations outside their scope, and intentional stubs reserving a name.,The most common shape is abstract base class contract enforcement. The base method is a stub whose only job is to fail loudly if a concrete subclass forgets to override it. Django's SessionBase declares exists(), save(), and create() this way and every built-in session backend overrides all three; redis-py's CredentialProvider leaves get_credentials() unimplemented to force subclasses to supply credentials; Celery's base Backend stubs _forget() and add_to_chord(); Django's FacetsMixin and BaseFinder do the same for get_facet_counts() and check(). In each case the base class carries the signature so the type system stays consistent, and NotImplementedError converts a silent missing override into an explicit, named failure the first time the method is touched.,The second shape is capability signaling, where a working class declines an operation because its backend, transport, or platform cannot honor it. Django's spatial layer raises NotImplementedError for geodetic area on MySQL, for distance and aggregates on backends that do not override the base operations stubs; Celery's RPC backend refuses chords because its per-client reply queues have no shared join counter; urllib3 v2 rejects proxy and CONNECT-tunnel configuration on its HTTP/2 connection because the h2 state machine is bound to a single direct TLS connection. Some of these are internal signals that never reach end users, Celery's stats() wrapper already catches the rusage NotImplementedError and returns 'N/A', while others escape to whoever made the call.,A third group covers restricted grammars, out-of-context operations, and mutually exclusive configuration. pandas's eval/query engine blocks AST nodes it does not support, Lambda, IfExp, GeneratorExp, Set, is/isNot, with a per-node NotImplementedError; its HDFStore where filter refuses arithmetic, non-invert unary operators, and joint filter combinations; SQLAlchemy refuses to delete individual mapped attributes or run executemany on a streaming server-side cursor; Alembic refuses create_table and drop_table inside a batch_alter_table block. From the caller's side the meaning across all these shapes is uniform: the library understood the request and tells you it is out of scope, and the remedy is to re-route, switch backend or subclass, precompute, or update the library, not to force the method through. One residual case behaves differently: boto3 raises NotImplementedError for unsupported identifier source types and untraversable response shape types when its bundled resource model JSON disagrees with the code, a symptom that boto3 and botocore were re-paired to incompatible versions by a partial install or an over-tight pin. Reinstalling the pair together resolves it without any change to calling code.

Common causes

What usually fixes it

Documented occurrences

…and 178 more across the corpus — use search.

Honest provenance: generated on 2026-08-12 from AI-assisted analysis of the linked records. See how records are made.