Troubleshooting Guide

Contents

Troubleshooting Guide#

This guide helps you diagnose and fix common issues with EngiAI.

Docker Issues#

Container Won’t Start#

Symptoms: Container exits immediately or fails health checks

Check logs:

docker-compose logs -f chatbot

Common Causes:

  1. Missing API keys:

    # Check your .env file
    cat .env | grep API_KEY
    

    Solution: Ensure OPENAI_API_KEY, GOOGLE_API_KEY, and TAVILY_API_KEY are set

  2. Port already in use:

    # Check what's using port 8501
    lsof -i :8501
    

    Solution: Stop the conflicting service or change port in docker-compose.yml

  3. Insufficient resources:

    • Increase Docker memory allocation (Docker Desktop → Settings → Resources)

    • Recommended: 4GB RAM minimum

Can’t Access UI#

Symptom: Browser can’t connect to http://localhost:8501

Steps:

  1. Check containers are running:

    docker-compose ps
    

    All containers should show “Up” status

  2. Check Docker Desktop is running (if using Docker Desktop)

  3. Try accessing via Docker host IP:

    # Find container IP
    docker inspect engiai-chatbot | grep IPAddress
    
  4. Check firewall settings (Linux):

    sudo ufw allow 8501
    

Permission Errors (Linux)#

Symptom: “Permission denied” errors

Solution: Add user to docker group:

sudo usermod -aG docker $USER
# Log out and back in for changes to take effect

Out of Disk Space#

Symptom: Build fails or containers crash

Check disk usage:

docker system df

Clean up:

# Remove unused images and containers
docker system prune -a

# Remove specific images
docker rmi $(docker images -q)

Local Development Issues#

Ruff Not Found in VS Code#

Symptom: VS Code shows “Ruff not found”

Solutions:

  1. Ensure conda environment is activated:

    conda activate engiai
    
  2. Restart VS Code after activating environment

  3. Set Python interpreter in VS Code:

    • Cmd/Ctrl + Shift + P → “Python: Select Interpreter”

    • Choose engiai conda environment

Pre-commit Not Working#

Symptom: Hooks don’t run on commit

Solutions:

  1. Reinstall hooks:

    pre-commit install
    
  2. Run manually to test:

    pre-commit run --all-files
    
  3. Skip hooks temporarily (not recommended):

    git commit --no-verify
    

Environment Creation Fails#

Symptom: conda env create fails

Solutions:

  1. Update conda:

    conda update -n base conda
    
  2. Clear conda cache:

    conda clean --all
    
  3. Try creating environment again:

    conda env remove -n engiai
    conda create -n engiai python=3.13 -y
    conda activate engiai
    pip install -e ".[dev,test]"
    

Import Errors#

Symptom: ModuleNotFoundError when running Python

Solutions:

  1. Verify environment is activated:

    conda activate engiai
    which python  # Should point to conda env
    
  2. Verify you’re in project root:

    pwd  # Should show .../engiai
    
  3. Reinstall package:

    pip install -e .
    

Streamlit Command Not Found#

Symptom: streamlit: command not found

Solution: Activate conda environment:

conda activate engiai
streamlit run src/ui/streamlit_app.py

API & Configuration Issues#

Missing API Keys Error#

Symptom: ValueError about missing configuration

Check .env file exists:

ls -la .env

If missing, create from example:

cp .env.example .env
# Edit .env and add your keys

Verify keys are set:

# Don't run this in production - just for debugging
cat .env | grep API_KEY

Chatbot Not Responding#

Symptoms: No response or timeout errors

Possible Causes:

  1. Invalid OpenAI API key:

    • Verify key at https://platform.openai.com/api-keys

    • Check you have sufficient credits

  2. API rate limiting:

    • Wait a few minutes and try again

    • Check OpenAI dashboard for rate limits

  3. Network issues:

    # Test connectivity
    curl https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"
    

Web Search Not Working#

Symptom: Search tool fails

Check the selected search provider:

  • The default SEARCH_PROVIDER=duckduckgo requires internet access but no key.

  • EngiAI uses DuckDuckGo Lite first. If DuckDuckGo temporarily blocks automated requests, it retries once and then uses keyless search-engine fallbacks. No Tavily credits are consumed in this mode.

  • For Tavily, verify SEARCH_PROVIDER=tavily and TAVILY_API_KEY in .env.

Database Errors#

Symptom: “database is locked” or connection errors

For SQLite:

# Close other applications using the database
# Or use PostgreSQL instead

For PostgreSQL:

  1. Check PostgreSQL is running:

    # Docker
    docker-compose ps postgres
    
    # Local (macOS)
    brew services list | grep postgresql
    
    # Local (Linux)
    sudo systemctl status postgresql
    
  2. Verify connection string:

    # Check DATABASE_URL in .env
    cat .env | grep DATABASE_URL
    
  3. For Docker, ensure hostname is postgres not localhost:

    # Correct for Docker
    DATABASE_URL=postgresql://user:pass@postgres:5432/engineer_assistant
    
    # Correct for local
    DATABASE_URL=sqlite:///data/conversations.db
    

“Could not translate host name ‘postgres’” (Local)#

Symptom: Error when running locally with Streamlit

Cause: Your .env is configured for Docker

Solution: Change DATABASE_URL to use SQLite:

# In .env file
DATABASE_URL=sqlite:///data/conversations.db

The whole stack fails to start after a Postgres major bump#

Symptom: make docker-up never finishes. docker compose logs postgres repeats:

FATAL:  database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 15,
        which is not compatible with this version 17.

Cause: a major version cannot read another major’s data directory. Postgres exits, restart: unless-stopped restarts it into the same failure, and because chatbot waits on condition: service_healthy nothing else comes up either — so the visible symptom is the whole stack hanging, not a database error.

Solution: see Upgrading the PostgreSQL major version. Short form, if the conversation history is expendable:

./docker-compose-wrapper.sh down
docker volume rm engiai_postgres_data
./docker-compose-wrapper.sh up -d

The app says “Falling back to SQLite” and every conversation is gone#

Symptom: the UI starts but the chat list is empty, and the logs show:

Could not connect to database (... FATAL: password authentication failed
for user "engiai_user"). Falling back to SQLite.

Cause: POSTGRES_PASSWORD and the password inside DATABASE_URL disagree. The first is what initdb gave the role when the volume was created; the second is what the app connects with. They can diverge for months without symptoms — the running database still has the old password — and the mismatch only appears once the volume is recreated.

Nothing is actually lost: the Postgres data is still in its volume, and the empty database you are looking at is a fresh SQLite file.

Solution: make them match in .env, then recreate the volume so initdb applies the intended password:

grep -E '^(POSTGRES_PASSWORD|DATABASE_URL)=' .env    # compare the two

MMORE / RAG Issues#

MMORE takes forever to become healthy on first start#

Expected. A cold start pulls ~1.5 GB of image plus the embedding, SPLADE and reranker weights. The healthcheck allows 600s for this, and the chatbot waits on the service being healthy, so the whole stack appears to hang.

docker compose logs -f mmore-rag-service   # watch the model downloads

The cache lives in data/mmore/cache/ and is shared with the evaluation service, so this cost is paid once. Start the main service and let it warm the cache before bringing up the eval service, rather than having both race the same download.

Search returns nothing, but the service is healthy#

The service starts fine with an empty index — health says nothing about content. Check what is actually indexed:

curl -s "http://localhost:8000/list_files?collection_name=my_docs"
make mmore-index-verify

If it is empty, build it: make mmore-index (or make mmore-index-eval for port 8001).

If documents are indexed but results still come back empty, the score threshold may be wrong for your MMORE version. The search_documents tool filters at MMORE_MIN_SIMILARITY (default 0.3); if an upstream bump changed the score scale, that floor can silently suppress everything. Compare raw scores with no floor:

python scripts/inspect_mmore.py --retrieve "topology optimization" --max-matches 10

409 Conflict when adding a document#

MMORE already holds that fileId. Upload does not overwrite. Either delete first, or replace in place:

curl -X DELETE http://localhost:8000/v1/files/<fileId>
# or, for a manifest document:
python scripts/build_mmore_index.py --only <file_id> --force

scripts/import_local_papers.py treats a 409 as “already imported” and moves on rather than retrying.

An upload seems to hang#

MMORE v2 indexes asynchronously, and upload_file blocks until the background job finishes — that is deliberate, so callers can assume “returned means searchable”. Large scanned PDFs on CPU genuinely take minutes. Inspect the job:

curl -s http://localhost:8000/v1/jobs/<jobId>   # queued | processing | done | failed

Raise MMORE_INDEX_TIMEOUT (default 900s) if legitimate work is being cut off. Note job records live in memory, expire after two hours, and are lost on restart — the durable answer to “is it indexed?” is /list_files.

Upload dies with “Connection reset by peer”#

Almost always the container being OOM-killed mid-job (docker inspect mmore-rag-service --format '{{.State.ExitCode}}' returns 137). Processing a PDF loads marker’s six models plus the embedding and reranker models, which peaks at several GB on top of whatever is already resident.

Two things make this much worse:

  • Both services indexing at once. The main and eval services each need the full pipeline in memory. Build one index at a time.

  • Models stay resident after a job. A service that has processed a PDF holds those models. docker restart mmore-rag-service releases them.

The reliable sequence on a memory-constrained host is:

docker restart mmore-rag-service   # drop retained models
make mmore-index
docker restart mmore-rag-service
make mmore-eval-up && make mmore-index-eval

If it still will not fit, raise Docker Desktop’s memory limit (Settings → Resources) or index on a larger machine and copy data/mmore/index/mmore.db across — it is a single portable file.

Permission denied writing the index (Linux)#

The container runs as uid 1000. If your host user differs, the bind mounts under data/mmore/ are not writable. Add a docker-compose.override.yml:

services:
  mmore-rag-service:
    user: "${UID}:${GID}"

Docker Desktop on macOS and Windows does not have this problem.

MMORE_PATH no longer does anything#

It pointed at a local MMORE source checkout that the stack no longer needs. Remove it from your .env. MMORE now runs from a pinned upstream image; see services/mmore/README.md.

Prusa MCP Issues#

MCP Connection Failed#

Symptom: Prusa agent can’t connect

Check MCP server is running:

# For Docker deployment
docker-compose ps prusa-mcp-server

# Test connection
curl http://localhost:8765/sse

Solutions:

  1. Check SKIP_MCP setting in .env:

    SKIP_MCP=true   # Disables MCP integration
    SKIP_MCP=false  # Enables MCP integration
    
  2. Verify MCP server is accessible:

    # From container
    docker exec engiai-chatbot curl -v http://prusa-mcp-server:8765/sse
    

Tools Not Loading#

Symptom: Prusa-related tools missing

Solution: Set SKIP_MCP=true to disable MCP integration if you don’t need 3D printing features

The assistant says printer control is unavailable#

Symptom: a printer question is answered with “3D printer control is not available in this context — the Prusa MCP server is not reachable.”

Cause: the agent loaded no tools, either because SKIP_MCP=true or because the server was down when the app started. Tools are loaded once at startup, so starting the server afterwards is not enough — restart the app too.

docker compose up -d prusa-mcp-server
docker compose restart chatbot

This message is deliberate. Before it existed the same situation produced a blank reply: with no tools bound, the model’s whole response is a tool call, which the agent strips rather than let it reach a tool that isn’t there.

Whiteboard Canvas Issues#

Fuller coverage lives in Whiteboard Canvas; this is the subset that gets mistaken for a broken app.

The assistant says it cannot draw#

Symptom: asked for a diagram, the assistant replies that the whiteboard is unavailable.

Cause: the canvas MCP server is not reachable, so the agent is dropped rather than offered — deliberately, so it can never claim to have drawn something it could not.

docker compose ps excalidraw-mcp-server
docker logs excalidraw-mcp-server | grep "allowed hosts"

Check SKIP_MCP and SKIP_CANVAS are both false. SKIP_MCP=true disables the canvas as well as the printer.

The app will not start with the canvas enabled#

Symptom: httpx2.ConnectError: All connection attempts failed at startup.

Cause: enabling the canvas means SKIP_MCP=false, which enables the Prusa agent too. Both servers need to be running, or start neither:

docker compose up -d prusa-mcp-server excalidraw-mcp-server

My drawing disappeared when the assistant drew#

Cause: it was never sent. The UI only learns what is on the canvas when you press 📤 Send to Chat, so an unsent drawing is replaced by whatever the assistant draws next. Send first.

Drawings vanish between sessions#

Scenes are stored per conversation in the EngiAI database and restored when you reopen the chat. If they are not coming back, the conversation may never have been saved — a chat with no messages is not written to the database, and its whiteboard goes with it.

Host Service & GUI Integration#

“Cannot connect to host service” Error#

Symptom: Can’t open PrusaSlicer or other GUI apps from Docker

Check host service is running:

lsof -i :9999

Start host service (on your local machine):

python services/host_service.py

Verify from Docker:

docker exec engiai-chatbot curl http://host.docker.internal:9999/health

PrusaSlicer Won’t Open#

Solutions:

  1. Verify PrusaSlicer is installed on host machine

  2. Verify host service whitelist includes the app (in services/host_service.py)

Port 9999 Already in Use#

Solution: Change port in .env:

HOST_SERVICE_PORT=9998

Then restart both host service and Docker containers.

SSH & HPC Connection Issues#

“SSH key is encrypted” Error (Docker)#

Symptom: Can’t connect to HPC cluster from Docker

Solution: Use SSH agent forwarding

  1. On host machine, add key to SSH agent:

    # macOS
    ssh-add --apple-use-keychain ~/.ssh/id_ed25519
    
    # Linux
    ssh-add ~/.ssh/id_ed25519
    
  2. Verify key is loaded:

    ssh-add -l
    
  3. Restart Docker container:

    docker-compose restart chatbot
    

“Agent has no identities” Error#

Check SSH agent is running:

echo $SSH_AUTH_SOCK
# Should show a path like: /private/tmp/com.apple.launchd.*/Listeners

Start SSH agent if needed:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

Connection Works Locally But Fails in Docker#

Checklist:

  1. ✅ SSH agent is running on host: ssh-add -l

  2. ✅ SSH_AUTH_SOCK environment variable is set

  3. ✅ ~/.ssh/config has AddKeysToAgent yes and UseKeychain yes

  4. ✅ Restart Docker after adding keys

SSH Key Permission Errors#

Fix permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/config
chmod 644 ~/.ssh/known_hosts

HPC Job Submission Fails#

Common Issues:

  1. Can’t connect to cluster:

    # Test SSH manually
    ssh your-cluster-alias
    
  2. SLURM commands not found:

    • Verify you’re on a login node

    • Check cluster documentation

  3. Job fails immediately:

    # Check job logs
    cat slurm-<jobid>.out
    cat slurm-<jobid>.err
    
  4. Module not found:

    # Check available modules
    module avail
    

Performance Issues#

Slow Response Times#

Possible Causes:

  1. Large document collection:

    • Monitor MMORE service performance

    • Consider limiting search scope with file_ids

  2. Slow API responses:

    • Check OpenAI API status

    • Try different model (e.g., gpt-4o-mini)

  3. Insufficient resources:

    • Increase Docker memory allocation

    • Close other applications

High Memory Usage#

Solutions:

  1. Limit conversation history length

  2. Clear browser cache

  3. Restart Docker containers:

    docker-compose restart
    

Streamlit Performance Issues#

Solutions:

  1. Reduce max tokens in settings

  2. Limit chat history length

  3. Use a smaller LLM model

  4. Close unused browser tabs

Clear Streamlit cache:

streamlit cache clear

Testing Issues#

Tests Failing#

Run tests with verbose output:

pytest -v

Run specific test:

pytest tests/test_specific_file.py -v

Skip slow tests:

pytest -m "not slow"

Import Errors in Tests#

Ensure package is installed:

pip install -e .

Common Error Messages#

“ModuleNotFoundError: No module named ‘src’”#

Solution: Install package in development mode:

pip install -e .

“ValueError: Invalid configuration”#

Solution: Check all required environment variables in .env

“Connection refused” (Port 8501)#

Solutions:

  1. Check Docker containers are running

  2. Check firewall settings

  3. Try different port in docker-compose.yml

“OSError: [Errno 28] No space left on device”#

Solution: Free up disk space or clean Docker:

docker system prune -a

Getting Help#

If your issue isn’t covered here:

  1. Check logs:

    # Docker
    docker compose logs -f chatbot
    
    # Local: the app logs to the terminal running Streamlit — there is no
    # application log file. (`data/local_import.log` is written only by
    # scripts/import_local_papers.py.)
    
  2. Search GitHub Issues: https://github.com/gioelemo/EngiAI/issues

  3. Open a new issue with:

    • Operating system

    • Python version

    • Full error message

    • Steps to reproduce

    • What you’ve tried

  4. Review documentation:

Prevention Tips#

  1. ✅ Always activate conda environment before running commands

  2. ✅ Keep .env file up to date with required keys

  3. ✅ Use Docker for consistent deployment

  4. ✅ Regularly update dependencies

  5. ✅ Back up your database regularly

  6. ✅ Monitor API usage and credits

  7. ✅ Test in development before deploying to production