django/django · error · NotImplementedError
subclasses of Storage must provide a listdir() method
Error message
subclasses of Storage must provide a listdir() method
What it means
Raised as NotImplementedError by the base Storage.listdir() abstract method. Subclasses must implement listdir(self, path) returning a 2-tuple of (directories, files) lists. The base raises at storage/base.py:164.
Source
Thrown at django/core/files/storage/base.py:164
raise NotImplementedError(
"subclasses of Storage must provide a delete() method"
)
def exists(self, name):
"""
Return True if a file referenced by the given name already exists in
the storage system, or False if the name is available for a new file.
"""
raise NotImplementedError(
"subclasses of Storage must provide an exists() method"
)
def listdir(self, path):
"""
List the contents of the specified path. Return a 2-tuple of lists:
the first item being directories, the second item being files.
"""
raise NotImplementedError(
"subclasses of Storage must provide a listdir() method"
)
def size(self, name):
"""
Return the total size, in bytes, of the file specified by name.
"""
raise NotImplementedError("subclasses of Storage must provide a size() method")
def url(self, name):
"""
Return an absolute URL where the file's contents can be accessed
directly by a web browser.
"""
raise NotImplementedError("subclasses of Storage must provide a url() method")
def get_accessed_time(self, name):
"""View on GitHub (pinned to b5388a3a80)
Solutions
- Implement listdir(self, path) in the custom Storage subclass, mapping the backend's list operation to the (dirs, files) tuple.
- Subclass an existing backend (FileSystemStorage) that implements listdir.
- Avoid calling storage.listdir() on remote backends; use backend-specific listing APIs directly.
- Document which storage methods are required before building a custom backend.
Example fix
# before
class MyStorage(Storage):
...
# after
class MyStorage(Storage):
def listdir(self, path):
dirs, files = [], []
for entry in self.client.list(path):
(dirs if entry.is_dir else files).append(entry.name)
return dirs, files Defensive patterns
Strategy: type-guard
Validate before calling
def storage_can_listdir(storage) -> bool:
return 'listdir' in storage.__class__.__dict__ Type guard
def implements_listdir(storage) -> bool:
return any('listdir' in c.__dict__ for c in storage.__class__.__mro__) Try / catch
try:
dirs, files = storage.listdir(path)
except NotImplementedError:
files = [] # fallback to backend-specific listing API Prevention
- Implement listdir(self, path) -> (dirs, files) in custom backends.
- Avoid storage.listdir() on remote backends; use native listing.
- Document required methods before building a custom storage.
When it happens
Trigger: Calling storage.listdir(path) on a Storage subclass that does not override listdir(). Commonly hit via admin 'collectstatic --list', static-files finders, or custom management commands that enumerate stored files.
Common situations: Custom object-storage backend without a listdir implementation; code using storage.listdir() for cleanup or reporting; static-files tooling that enumerates a custom storage.
Related errors
- subclasses of Storage must provide a delete() method
- subclasses of Storage must provide an exists() method
- subclasses of Storage must provide a size() method
- subclasses of Storage must provide a url() method
- subclasses of SessionBase must provide an exists() method
AI-assisted analysis of django/django@b5388a3a80 (2026-08-10).
Data as JSON: /api/errors/51e70db94d2c7144.
Report an issue: GitHub.