RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /stores/$1 [NC,L]
The "problem" with this rule is that if you make a request for a non-existent file and that file not exist in the /stores/ subdirectory either then it will result in an endless rewrite-loop (hence the 500 Internal Server Error you are seeing) since it will attempt to rewrite as follows:
/not-exists (initial request)
/stores/not-exists (1st rewrite)
/stores/stores/not-exists (2nd pass)
/stores/stores/stores/not-exists (3rd pass)
- etc.
You've not actually stated what you are trying to achieve here, but I assume /stores is a "hidden" subdirectory and you are intending to rewrite to actual files within the /stores subdirectory. This is the only way a rule like this would work with an ErrorDocument 404 directive defined in Apache.
So, when rewriting to the /stores subdirectory, you need to first check that the request would map to an actual file before issuing the rewrite. That way, any request that does not exist and does not map to a file in the /stores subdirectory will drop through to the Apache defined 404 ErrorDocument.
For example, try the following instead:
ErrorDocument 404 /404.html
RewriteEngine On
# Rewrite request to "/stores" directory if file exists in that directory
RewriteCond %{DOCUMENT_ROOT}/stores/$1 -f
RewriteRule (.+) stores/$1 [L]
# (OPTIONAL) Rewrite requests for root to "/stores/"
RewriteRule ^$ stores/ [L]
The <IfModule> container is not required (but you had the RewriteEngine directive outside of this container - which defeats the point anyway).
The RewriteBase directive is not required here if the .htaccess file is located in the document root.
It is structurally better to define your ErrorDocuments first.