Skip to content

Commit a828d21

Browse files
Fix SSL certificate handling to prevent startup crash
Fixes a critical bug where the application would crash on startup with `FileNotFoundError` when `SSL_CERT_FILE` was set to an empty string. The httpx library (used by OpenAI client) fails when `SSL_CERT_FILE` points to a non-existent file or empty string. **Changes:** - Removed empty `SSL_CERT_FILE` and `REQUESTS_CA_BUNDLE` from `docker-compose.yaml` - Improved SSL certificate validation in `app_factory.py` to handle empty strings before httpx initialization - Removed unused `document_routes_v2` import (already conditionally loaded in routers) **Impact:** - Application now starts successfully without SSL certificate errors - httpx automatically uses system certificate defaults when `SSL_CERT_FILE` is not set - Better error handling for invalid certificate paths Fixes startup crash that prevented Docker containers from running.
1 parent 7871626 commit a828d21

3 files changed

Lines changed: 25 additions & 26 deletions

File tree

README.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -417,15 +417,6 @@ This project is licensed under the GNU Affero General Public License v3.0 - see
417417
- **Discussions**: [GitHub Discussions](https://github.com/Papr-ai/memory-opensource/discussions)
418418
- **Discord**: Join our community for real-time support: https://discord.gg/sWpR5a3H
419419

420-
## 🗺️ Roadmap
421-
422-
- [ ] **Enhanced Graph Relationships**: Automatic relationship extraction from content
423-
- [ ] **Multi-Modal Support**: Image and audio memory storage
424-
- [ ] **Advanced Search**: Hybrid search combining vector and graph traversal
425-
- [ ] **Real-time Collaboration**: Live memory sharing and editing
426-
- [ ] **Mobile SDK**: Native mobile app integration
427-
- [ ] **Enterprise Features**: Advanced ACL, audit logs, and compliance
428-
- [ ] **MongoDB Migration**: Remove Parse Server dependency (planned)
429420

430421
---
431422

app_factory.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@
2424
# This check happens early to prevent httpx errors when OpenAI client initializes
2525
if 'SSL_CERT_FILE' in os.environ:
2626
ssl_cert_file = os.environ['SSL_CERT_FILE']
27-
cert_path = Path(ssl_cert_file)
28-
if not cert_path.exists() or not cert_path.is_file() or not os.access(ssl_cert_file, os.R_OK):
29-
# Unset if file doesn't exist or isn't readable - httpx will use system defaults
27+
# Handle empty string (httpx will fail if SSL_CERT_FILE is empty)
28+
if not ssl_cert_file or not ssl_cert_file.strip():
3029
del os.environ['SSL_CERT_FILE']
31-
try:
32-
logger = LoggerSingleton.get_logger(__name__)
33-
logger.warning(f"SSL_CERT_FILE points to non-existent or unreadable file: {ssl_cert_file}, unsetting to use system defaults")
34-
except:
35-
# Logger might not be initialized yet, just print
36-
print(f"WARNING: SSL_CERT_FILE points to non-existent or unreadable file: {ssl_cert_file}, unsetting to use system defaults")
30+
else:
31+
cert_path = Path(ssl_cert_file)
32+
if not cert_path.exists() or not cert_path.is_file() or not os.access(ssl_cert_file, os.R_OK):
33+
# Unset if file doesn't exist or isn't readable - httpx will use system defaults
34+
del os.environ['SSL_CERT_FILE']
35+
try:
36+
logger = LoggerSingleton.get_logger(__name__)
37+
logger.warning(f"SSL_CERT_FILE points to non-existent or unreadable file: {ssl_cert_file}, unsetting to use system defaults")
38+
except:
39+
# Logger might not be initialized yet, just print
40+
print(f"WARNING: SSL_CERT_FILE points to non-existent or unreadable file: {ssl_cert_file}, unsetting to use system defaults")
3741
from fastapi.security import HTTPBearer, APIKeyHeader
3842
from core.services.telemetry import get_telemetry
3943
from routers.v1 import v1_router
@@ -344,13 +348,18 @@ async def authenticate(self, request):
344348
# httpx (used by OpenAI) reads SSL_CERT_FILE directly and fails if file doesn't exist
345349
if 'SSL_CERT_FILE' in os.environ:
346350
ssl_cert_file = os.environ['SSL_CERT_FILE']
347-
cert_path = Path(ssl_cert_file)
348-
if not cert_path.exists() or not cert_path.is_file() or not os.access(ssl_cert_file, os.R_OK):
349-
# Unset if file doesn't exist or isn't readable - httpx will use system defaults
351+
# Handle empty string (httpx will fail if SSL_CERT_FILE is empty)
352+
if not ssl_cert_file or not ssl_cert_file.strip():
350353
del os.environ['SSL_CERT_FILE']
351-
logger.warning(f"SSL_CERT_FILE points to non-existent or unreadable file: {ssl_cert_file}, unsetting to use system defaults")
354+
logger.debug("SSL_CERT_FILE was empty, unset to use system defaults")
352355
else:
353-
logger.debug(f"SSL_CERT_FILE validated: {ssl_cert_file}")
356+
cert_path = Path(ssl_cert_file)
357+
if not cert_path.exists() or not cert_path.is_file() or not os.access(ssl_cert_file, os.R_OK):
358+
# Unset if file doesn't exist or isn't readable - httpx will use system defaults
359+
del os.environ['SSL_CERT_FILE']
360+
logger.warning(f"SSL_CERT_FILE points to non-existent or unreadable file: {ssl_cert_file}, unsetting to use system defaults")
361+
else:
362+
logger.debug(f"SSL_CERT_FILE validated: {ssl_cert_file}")
354363

355364
chat_gpt = ChatGPTCompletion(api_key, organization_id, env.get("LLM_MODEL"), env.get("LLM_LOCATION_CLOUD", default=True), env.get("EMBEDDING_MODEL_LOCAL"))
356365
app.state.chat_gpt = chat_gpt

docker-compose.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,9 @@ services:
4646
PARSE_SERVER_MASTER_KEY: ${PARSE_SERVER_MASTER_KEY:-papr-oss-master-key}
4747
# Memory Server URL (for open source, set to localhost)
4848
PYTHON_SERVER_URL: ${PYTHON_SERVER_URL:-http://localhost:5001}
49-
# SSL certificates - unset to let httpx use system defaults (prevents FileNotFoundError)
49+
# SSL certificates - don't set SSL_CERT_FILE (let httpx use system defaults)
50+
# If SSL_CERT_FILE is set to empty string, httpx will fail
5051
# The code will auto-detect and set SSL_CERT_FILE only if the file exists
51-
SSL_CERT_FILE: ""
52-
REQUESTS_CA_BUNDLE: ""
5352
# Fix protobuf compatibility issue with sentencepiece (BigBird tokenizer)
5453
# This uses pure-Python protobuf implementation to avoid version conflicts
5554
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python

0 commit comments

Comments
 (0)