Problem: RAG pipeline returns empty retrieval results on an AWS EC2 instance (local development)
During local development on an EC2 t3.medium (Ubuntu 22.04) the LangChain retrieval‑augmented generation (RAG) pipeline executes without errors but always yields the log message “No documents found”. The same code runs correctly on a developer laptop.
Typical symptom in the application logs:
2026-09-18 10:12:34,567 - langchain.retrievers - INFO - Retrieval result: []
2026-09-18 10:12:34,568 - langchain.chains - WARNING - No documents found for query: "What is the refund policy?"
Other observed errors that may appear intermittently:
ConnectionError: [Errno 111] Connection refused– when the vector store endpoint cannot be reached.AWS credentials not found– when the instance role lacks required permissions.RuntimeError: FAISS index not loaded – file not found or corrupted– when the index file is missing or unreadable.MemoryError: unable to allocate X bytes for FAISS index– when the instance runs out of RAM.
Root Cause Analysis
The empty retrieval result is rarely caused by a single factor. In production‑grade EC2 environments the following interactions are the most common culprits, as documented in the evidence package:
| Potential Cause | Why it leads to empty results | Evidence Source |
|---|---|---|
| Security group blocks outbound HTTPS/9200 | Vector store (OpenSearch, Elasticsearch) cannot be contacted; LangChain falls back to an empty list without raising a hard error. | deepset‑ai/haystack#3841 |
IAM role missing s3:GetObject for index bucket |
FAISS index stored in S3 fails to download; the loader silently returns an empty index. | Real incident – missing S3 permissions |
| Missing runtime library (libtorch, libstdc++) | FAISS backend crashes during index load, raising RuntimeError that is caught and logged as “No documents found”. |
langchain‑ai/langchain#5872 |
| Insufficient RAM for FAISS index | Index load aborts with MemoryError; the pipeline proceeds with an empty in‑memory store. |
Reddit discussion on FAISS RAM limits |
Incorrect AWS_REGION or missing env var |
Boto3 cannot resolve the OpenSearch endpoint, resulting in a connection failure. | Stack Overflow – missing AWS_REGION |
In the specific incident described in the evidence package, two root causes overlapped:
- The EC2 instance’s security group lacked outbound HTTPS (port 443) and OpenSearch port 9200, preventing the vector store from being reached.
- The attached IAM role did not include
s3:GetObjectfor the bucket that holds the pre‑computed FAISS index, so the index never loaded.
Investigation and Debugging Steps
1. Verify network connectivity to the vector store
# Replace with your OpenSearch endpoint
ENDPOINT="search-my-rag-domain.us-east-1.es.amazonaws.com"
# Test TCP connectivity on port 443 (HTTPS) and 9200 (OpenSearch)
nc -zv $ENDPOINT 443
nc -zv $ENDPOINT 9200
Expected output when the security group allows traffic:
Connection to search-my-rag-domain.us-east-1.es.amazonaws.com 443 port [tcp/https] succeeded!
Connection to search-my-rag-domain.us-east-1.es.amazonaws.com 9200 port [tcp/elasticsearch] succeeded!
If you see Connection timed out or Connection refused, inspect the EC2 security group and any VPC NACLs (AWS EC2 User Guide – Networking and Security).
2. Check IAM role permissions
aws sts get-caller-identity
aws iam get-role --role-name MyRagInstanceRole
aws iam list-attached-role-policies --role-name MyRagInstanceRole
Ensure the role includes policies such as AmazonS3ReadOnlyAccess (or a custom policy with s3:GetObject) and AmazonOpenSearchServiceFullAccess for the OpenSearch domain.
3. Confirm environment variables
echo $AWS_REGION
echo $OPENSEARCH_ENDPOINT
If AWS_REGION is empty, LangChain’s OpenSearch client cannot resolve the endpoint, leading to silent failures (Stack Overflow reference).
4. Validate FAISS index loading
python - <<'PY'
from langchain.vectorstores import FAISS
import os
index_path = os.getenv("FAISS_INDEX_PATH", "/data/faiss.index")
try:
vectorstore = FAISS.load_local(index_path, embeddings)
print("FAISS index loaded, vectors:", len(vectorstore.index_to_docstore_id))
except Exception as e:
print("FAISS load error:", e)
PY
Typical error when the index file is missing or unreadable:
FAISS load error: RuntimeError: FAISS index not loaded – file not found or corrupted
5. Inspect application logs for suppressed exceptions
LangChain often catches RuntimeError from the vector store and logs only “No documents found”. Increase log verbosity:
export LANGCHAIN_LOG_LEVEL=DEBUG
python run_rag.py
Look for stack traces that point to network timeouts or permission errors.
Resolution
1. Update Security Group
Allow outbound HTTPS (443) and OpenSearch (9200) to the VPC endpoint or public OpenSearch domain.
| Rule | Type | Protocol | Port | Destination |
|---|---|---|---|---|
| Outbound 1 | HTTPS | TCP | 443 | 0.0.0.0/0 (or VPC CIDR) |
| Outbound 2 | OpenSearch | TCP | 9200 | VPC CIDR or specific OpenSearch SG |
Example AWS CLI command:
aws ec2 authorize-security-group-egress \
--group-id sg-0abc123def456ghi \
--protocol tcp --port 443 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-egress \
--group-id sg-0abc123def456ghi \
--protocol tcp --port 9200 --cidr 10.0.0.0/16
2. Attach a proper IAM role
Create or modify a role with the required policies and associate it with the EC2 instance.
aws iam create-policy \
--policy-name RAGS3ReadAccess \
--policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::my-rag-bucket/*"]
}]
}'
aws iam attach-role-policy \
--role-name MyRagInstanceRole \
--policy-arn arn:aws:iam::123456789012:policy/RAGS3ReadAccess
3. Install missing runtime libraries
On Ubuntu, ensure libtorch and libstdc++6 are present:
sudo apt-get update
sudo apt-get install -y libtorch-dev libstdc++6
After installation, re‑run the index loader to confirm the FAISS index loads without RuntimeError.
4. Set required environment variables
# .bashrc or systemd service file
export AWS_REGION=us-east-1
export OPENSEARCH_ENDPOINT=https://search-my-rag-domain.us-east-1.es.amazonaws.com
export FAISS_INDEX_PATH=/data/faiss.index
5. Adjust instance size if RAM is insufficient
FAISS indexes for >10k documents often need >4 GiB of RAM. Upgrade to t3.large or add swap space as a temporary mitigation.
# Add 2 GiB swap
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
Verification
After applying the fixes, run the pipeline with debug logging and confirm that documents are returned.
export LANGCHAIN_LOG_LEVEL=DEBUG
python run_rag.py "What is the refund policy?"
Expected log excerpt:
2026-09-18 10:45:12,001 - langchain.retrievers - INFO - Retrieval result: [{'page_content': 'Our refund policy ...', 'metadata': {...}}]
2026-09-18 10:45:12,005 - langchain.chains - INFO - Generated answer: "The refund policy allows ..."
Additional validation steps:
- Run
curl -s $OPENSEARCH_ENDPOINT/_cat/indices?vto ensure the OpenSearch index is visible. - Check CloudWatch metrics for successful
Searchrequests (HTTP 200) from the EC2 instance. - Execute a unit test that queries the vector store directly and asserts
len(results) > 0.
Prevention and Best Practices
- Network hygiene: Keep a dedicated security group for RAG instances that explicitly allows outbound traffic to vector store ports (443, 9200) and inbound health‑check ports if needed.
- IAM least‑privilege: Attach a role with only
s3:GetObjectfor the index bucket andes:ESHttp*for the OpenSearch domain. - Dependency management: Pin OS packages (e.g.,
libtorch,libstdc++6) in a Dockerfile or AMI image; verify them after OS upgrades. - Resource sizing: Profile FAISS index memory usage; provision instances with at least 2× the estimated RAM requirement.
- Health checks: Add a startup script that attempts a simple vector store query and aborts the service if the result list is empty.
- Observability: Emit a custom CloudWatch metric “RAGEmptyRetrievals” and set an alarm when the count exceeds a threshold.
Related Topic Hub: Cloud Infrastructure Troubleshooting Hub
FAQ
- Why does the RAG pipeline work on my laptop but not on EC2?
The laptop typically runs with unrestricted outbound internet access and has the required libraries installed. EC2 instances are isolated by security groups, VPC endpoints, and IAM roles, which can block network traffic or deny S3/OpenSearch access.
- What does “ConnectionError: [Errno 111] Connection refused” indicate in this context?
The EC2 security group or VPC NACL is blocking the port used by the vector store (usually 443 for HTTPS or 9200 for OpenSearch). Updating the outbound rules resolves the error.
- How can I confirm that the FAISS index was actually loaded?
After calling
FAISS.load_local(), print the number of vectors:len(vectorstore.index_to_docstore_id). A non‑zero count confirms a successful load. - Is the
AWS_REGIONenvironment variable always required?Yes. Boto3 uses
AWS_REGIONto construct the endpoint for services like OpenSearch. Missing or mismatched values cause endpoint resolution failures (Stack Overflow evidence). - Can insufficient RAM cause the index to load silently?
FAISS raises a
MemoryErrorwhen allocation fails. If the exception is caught and ignored by the application, the pipeline proceeds with an empty in‑memory store, resulting in “No documents found”. Monitoring RAM usage and provisioning adequate instance size prevents this.