Skip to content

Troubleshooting

homelabforge edited this page Oct 18, 2026 · 12 revisions

Troubleshooting Guide

Comprehensive troubleshooting for common MyGarage issues, organized by category.


Table of Contents


Installation Issues

Container Won't Start

Symptoms:

  • docker ps doesn't show mygarage container
  • Container immediately stops after docker-compose up -d

Diagnosis:

# Check container logs
docker logs mygarage

# Check container status
docker ps -a | grep mygarage

Common Causes & Solutions:

Port Already in Use

Error: Bind for 0.0.0.0:8686 failed: port is already allocated

Fix:

# Change port in docker-compose.yml
ports:
  - "8687:8686"  # Use 8687 instead

Or find what's using port 8686:

sudo lsof -i :8686
# Kill the process or change MyGarage port

Permission Errors

Error: Permission denied: '/data/mygarage.db'

Fix:

# Ensure data directory is writable
chmod -R 755 ./data

# Or change ownership to match container user (UID 1000)
sudo chown -R 1000:1000 ./data

Database Connection Error (PostgreSQL)

Error: FATAL: password authentication failed for user "mygarage"

Fix:

  1. Verify POSTGRES_PASSWORD matches MYGARAGE_DATABASE_URL
  2. Ensure PostgreSQL container is running: docker ps | grep postgres
  3. Check PostgreSQL logs: docker logs mygarage-postgres
  4. Reset password:
    docker exec mygarage-postgres psql -U postgres -c "ALTER USER mygarage WITH PASSWORD 'new-password';"

Cannot Access Web Interface

Symptoms:

Diagnosis:

# Verify container is running
docker ps | grep mygarage

# Check if MyGarage is listening
curl http://localhost:8686/health

# Check container logs for errors
docker logs mygarage

Solutions:

Firewall Blocking Port

# Allow port 8686 (Ubuntu/Debian)
sudo ufw allow 8686/tcp

# Allow port 8686 (CentOS/RHEL)
sudo firewall-cmd --permanent --add-port=8686/tcp
sudo firewall-cmd --reload

Wrong IP Address

If accessing from another device:

  • Don't use localhost - use server IP (e.g., http://192.168.1.100:8686)
  • Verify server IP: ip addr show or ifconfig

Docker Network Issue

# Restart Docker networking
docker-compose down
docker-compose up -d

Database Migration Fails on Startup

MyGarage uses a custom migration runner (not Alembic). Migrations live in backend/app/migrations/NNN_*.py and are tracked in the schema_migrations table; the app stops on the first failed migration.

Fix:

# Find the failing migration number and error
docker logs mygarage

# Back up the database before any manual intervention
cp data/mygarage.db data/mygarage-backup.db

Report the failing migration and error on GitHub, then restore from backup if needed.


Bun Development Issues

Note: MyGarage frontend uses Bun (currently 1.4.2; it replaced Node.js in v2.14.3). These troubleshooting steps apply to local development only.

"Command not found: bun"

Symptoms:

  • bun: command not found when trying to run bun install or bun dev

Fix:

# Install Bun
curl -fsSL https://bun.sh/install | bash

# Reload shell
source ~/.bashrc  # or ~/.zshrc

# Verify installation
bun --version  # Should show 1.4.2 or higher

"lockfile out of sync"

Error: error: lockfile had changes, but lockfile is frozen

Fix:

# Regenerate lockfile
rm bun.lock
bun install

# Or force install (if you know dependencies haven't changed)
bun install --force

"Module not found" Errors

Symptoms:

  • Import errors after bun install
  • Missing dependencies in node_modules

Fix:

# Clean install
cd frontend
rm -rf node_modules bun.lock
bun install

# If still failing, check package.json for typos

HMR Not Working in Development

Symptoms:

  • Changes to React components don't update in browser
  • Have to manually refresh to see changes

Diagnosis:

# Check if Vite dev server is running
curl http://localhost:3000

Fixes:

1. Clear Vite cache:

rm -rf node_modules/.vite
bun dev

2. Hard refresh browser:

  • Chrome/Firefox/Edge: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)
  • Safari: Cmd+Option+R

3. Restart dev server:

# Stop server (Ctrl+C), then:
bun dev

4. Check browser console:

  • Open DevTools (F12)
  • Look for WebSocket connection errors
  • HMR uses WebSocket on ws://localhost:3000

5. Firewall/proxy issues:

# Try disabling browser extensions
# Check if firewall is blocking WebSocket connections

Build Fails

Error: Various TypeScript or build errors

Fix:

# Clear cache and rebuild
cd frontend
rm -rf dist node_modules/.vite
bun install
bun run build

# Check for type errors
bun run type-check

# Check for lint errors
bun run lint

Tests Failing

Error: Vitest tests fail unexpectedly

Use bun run test:run. Plain bun test starts Bun's own test runner, not Vitest.

Fix:

# Run tests with verbose output
bun run test:run --reporter=verbose

# Run specific test file
bun run test:run src/pages/__tests__/Dashboard.defaultSort.test.tsx

# Clear the Vite and Vitest cache
rm -rf node_modules/.vite
bun run test:run

Slow Performance

Symptoms:

  • bun install taking >30 seconds
  • bun dev slow to start
  • Build times >10 seconds

Diagnosis:

# Check Bun version (should be 1.4.2+)
bun --version

# Check disk space
df -h

# Check if antivirus is scanning node_modules

Fixes:

  1. Upgrade Bun to latest: bun upgrade
  2. Exclude node_modules from antivirus scans
  3. Use SSD instead of HDD for development
  4. Close resource-intensive applications

Authentication Problems

Locked Out (Forgot Password)

Scenario: Only user, forgot password, can't login

Solutions:

Option 1: Reset Database (Loses All Data)

docker-compose stop mygarage
rm data/mygarage.db
docker-compose start mygarage
# Re-register at web interface

Option 2: Restore from Backup

docker-compose stop mygarage
cp data/mygarage-backup.db data/mygarage.db
rm -f data/mygarage.db-wal data/mygarage.db-shm
docker-compose start mygarage

Option 3: Set a New Password From the Command Line

Settings can't help once nobody can sign in, so set the password in the database. This keeps all your data. First make a hash of the new password inside the container:

docker exec -it mygarage python3 -c "import getpass; from app.services.auth import hash_password; print(hash_password(getpass.getpass('New password: ')))"

Then store it on your account, with your username and the hash it printed. SQLite:

docker exec -it mygarage python3 -c "import sqlite3, sys; db = sqlite3.connect('/data/mygarage.db'); n = db.execute('UPDATE users SET hashed_password = ? WHERE username = ?', (sys.argv[1], sys.argv[2])).rowcount; db.commit(); print(n, 'account updated')" 'PASTE_THE_HASH' 'your-username'

PostgreSQL: run UPDATE users SET hashed_password = '...' WHERE username = '...'; with psql. Sign in with the new password straight away; no restart is needed. 0 account updated means the username didn't match (it is case-sensitive). This works for an account that only signs in through SSO too: it gives the account a password, which then works alongside SSO.

"Invalid Credentials" on Login

Cause: Wrong username or password. The page says "Incorrect username or password".

Solutions:

  • Sign in with your username, not your email address (it is case-sensitive)
  • Check Caps Lock
  • Try password reset (if admin user exists)
  • Check container logs for rate limiting: docker logs mygarage | grep "rate limit"

Rate Limited (Too Many Login Attempts)

Error: 429 Too Many Requests. SSO sign-in shows "Too many sign-in attempts" on the login page instead.

Cause: More than 5 sign-in requests in 1 minute from one address

Fix: Wait a minute, then try again

If everyone gets limited at once and MyGarage sits behind a reverse proxy, MyGarage is seeing the proxy as every client. See Client IP and Rate Limits.

Admin Override:

# Restart container to reset rate limits
docker restart mygarage

OIDC Authentication Fails

A refused or failed SSO sign-in returns to the sign-in page with a sentence saying why. When it says single sign-on didn't work, docker logs mygarage has the cause.

Error: Invalid redirect URI

Cause: Redirect URI mismatch between MyGarage and OIDC provider

Fix:

  1. Copy the Redirect URI from MyGarage (Settings → System → OIDC section)
  2. Add this exact URI to your OIDC provider's allowed redirect URIs
  3. Ensure you don't mix http/https
  4. The path should end with /auth/oidc/callback

Error: OIDC claims missing email in the log

Cause: OIDC provider not returning email

Fix:

  1. Ensure email scope is requested
  2. Configure OIDC provider to include email in ID token claims
  3. Check OIDC provider documentation for claim configuration

Database Issues

"Database is Locked" (SQLite)

Symptoms:

  • Error: database is locked

Since v2.30, MyGarage runs SQLite in WAL mode with a 30-second busy_timeout, so this error should not occur under normal concurrent writes. If it still appears:

  • Ensure the data volume is on local storage — network filesystems (NFS/SMB) don't implement SQLite locking reliably.
  • Check the disk isn't full: df -h.
  • If the database is corrupted, see Database Corruption below.

Database Corruption

Symptoms:

  • Errors mentioning "malformed" or "corrupt"
  • Missing data
  • Container crashes on startup

Diagnosis (the image has no sqlite3 command, so this uses Python):

# Check SQLite integrity; "ok" means no corruption found
docker exec mygarage python3 -c "import sqlite3; print(sqlite3.connect('/data/mygarage.db').execute('PRAGMA integrity_check').fetchone()[0])"

If corrupted, restore from backup:

docker-compose stop mygarage
cp data/mygarage-backup.db data/mygarage.db
rm -f data/mygarage.db-wal data/mygarage.db-shm
docker-compose start mygarage

PostgreSQL Connection Timeout

Error: could not connect to server: Connection timed out

Diagnosis:

# Check PostgreSQL is running
docker ps | grep postgres

# Test connection
docker exec mygarage-postgres psql -U mygarage -c "SELECT 1;"

# Check PostgreSQL logs
docker logs mygarage-postgres

Solutions:

PostgreSQL Not Started

docker-compose up -d postgres
# Wait for PostgreSQL to fully start (check logs)
docker-compose up -d mygarage

Wrong Hostname

# Verify hostname matches container name
environment:
  - MYGARAGE_DATABASE_URL=postgresql+asyncpg://user:pass@mygarage-postgres:5432/mygarage
  #                                                        ^^^^^^^^^^^^^^^^
  #                                                        Must match container name

Network Issue

# Ensure containers are on same network
docker network inspect mygarage_default
# Look for both containers

VIN Decoder Errors

"Invalid VIN" Error

Causes:

  • VIN not 17 characters
  • VIN contains invalid characters (O, I, Q not allowed)
  • Incorrect VIN entered

Solution:

  • Verify VIN from registration or door jamb sticker
  • VINs are always 17 characters (no spaces)
  • Letters O, I, Q are never used (to avoid confusion with 0, 1, Q)

"VIN Not Found in Database"

Causes:

  • Non-US vehicle (NHTSA database is US-only)
  • Vehicle older than 1981 (pre-standardized VINs)
  • Commercial vehicle, RV, or motorcycle (limited data)

Solution: Use manual entry instead of VIN decoder

VIN Decoder Returns Partial Data

Expected Behavior: NHTSA database doesn't have complete data for all vehicles.

Solution:

  • Fill in missing fields manually after decoding
  • Edit vehicle after creation to add trim, color, etc.

"VIN Decoder Service Unavailable"

Error: 503 Service Unavailable or timeout

Cause: NHTSA vPIC API is down or slow

Solutions:

  1. Wait 5-10 minutes and try again
  2. Use manual entry
  3. Check NHTSA API status: https://vpic.nhtsa.dot.gov/api/

File Upload Problems

Upload Fails (No Error Message)

Diagnosis:

# Check container logs
docker logs mygarage | grep -i "upload\|error"

# Check disk space
df -h | grep /srv/raid0

Common Causes:

File Too Large

Limits:

  • Photos: 10MB
  • Documents (PDF): 25MB

Solution: Compress file before uploading

  • Images: Use TinyPNG, ImageOptim, or similar
  • PDFs: Use Adobe Acrobat or online PDF compressor

Disk Full

Error in logs: No space left on device

Solution:

# Check disk usage
df -h

# Clear Docker cache
docker system prune -a --volumes

# Move data to larger disk

Browser Timeout (Slow Connection)

Solution:

  • Use wired connection instead of Wi-Fi
  • Compress files before uploading
  • Upload one file at a time

"Invalid File Type" Error

Cause: Unsupported file extension

Supported Types:

  • Photos: JPG, JPEG, PNG, WEBP, HEIC, HEIF
  • Documents: PDF, DOC, DOCX, XLS, XLSX, TXT, CSV, JPG, JPEG, PNG
  • Receipts and attachments: PDF, JPG, JPEG, PNG, GIF

Solution: Convert file to supported format

  • .tiff → .jpg or .pdf

OCR Issues

OCR only fills in a form from an upload: Import from PDF on an insurance policy, Upload Window Sticker on a vehicle, and, if you turn on the LLM receipt parser in Settings → Integrations, Parse receipt on a fuel entry. It reads typed English text. Stored documents are never read or indexed (see Documents).

OCR Not Extracting Text

Possible Causes:

Low Quality Scan

Solution:

  • Re-scan at 300 DPI or higher
  • Ensure good lighting (no shadows, glare)
  • Use scanner instead of phone camera if possible
  • Keep document flat (not wrinkled or curved)

Handwritten Document

Expected Behavior: OCR reads typed text, not handwriting

Solution: Fill in the form by hand

Non-English Text

Current Limitation: OCR is configured for English only

Workaround: Fill in the form by hand

Extracted Text is Garbled

Causes:

  • Poor scan quality
  • Faded thermal receipt paper
  • Low contrast (light text on light background)

Solutions:

  • Increase scan contrast before uploading
  • Re-scan with higher resolution
  • Fill in the form by hand

OCR Takes Too Long

Expected: OCR can take 10-30 seconds for multi-page PDFs

If longer than 2 minutes:

# Check CPU usage
docker stats mygarage

# If CPU is maxed, increase Docker resources
# Docker Desktop → Settings → Resources → CPUs (increase to 2+)

Reverse Proxy Problems

"502 Bad Gateway" (Nginx/Caddy)

Cause: Reverse proxy can't reach MyGarage

Diagnosis:

# Verify MyGarage is running
docker ps | grep mygarage

# Test MyGarage health endpoint
curl http://localhost:8686/health

# Check reverse proxy logs
sudo tail -f /var/log/nginx/error.log

Solutions:

Wrong Upstream Address

Nginx:

# If MyGarage is Docker container on same host
location / {
    proxy_pass http://127.0.0.1:8686;  # NOT localhost:8686
    # ...
}

# If using Docker networks
location / {
    proxy_pass http://mygarage:8686;  # Container name
    # ...
}

Network Isolation

If reverse proxy is in Docker, ensure same network:

networks:
  - traefik-proxy  # Both reverse proxy and MyGarage must be on this network

"Too Many Redirects" Loop

Cause: Both reverse proxy and MyGarage forcing HTTPS redirects

Solution: Ensure X-Forwarded-Proto header is set correctly

Nginx:

proxy_set_header X-Forwarded-Proto $scheme;

Traefik: Handled automatically

SSL Certificate Errors

"Certificate not valid"

Cause: Let's Encrypt certificate failed to generate

Diagnosis:

# Check Certbot logs (Nginx)
sudo cat /var/log/letsencrypt/letsencrypt.log

# Check Traefik logs
docker logs traefik

Common Issues:

Domain Not Resolving:

# Verify DNS
nslookup garage.example.com

# Ensure A record points to your server IP

Port 80 Not Open (required for Let's Encrypt HTTP challenge):

sudo ufw allow 80/tcp

Rate Limit Hit:

  • Let's Encrypt allows 50 certs per domain per week
  • Use staging environment for testing
  • Wait 7 days for limit reset

"NET::ERR_CERT_AUTHORITY_INVALID"

Cause: Using Let's Encrypt staging certificates

Solution: Switch to production:

Certbot:

sudo certbot --nginx -d garage.example.com  # Remove --staging flag

Traefik:

# Remove staging certificatesResolvers config
certificatesResolvers:
  letsencrypt:
    acme:
      # caServer: https://acme-staging-v02.api.letsencrypt.org/directory  # Remove this line

Performance Issues

Slow Page Loads

Diagnosis:

# Check resource usage
docker stats mygarage

# Check database size
ls -lh data/mygarage.db

Common Causes & Solutions:

Database Too Large (SQLite)

If > 500MB or > 10,000 records:

  1. Vacuum database:
    docker exec mygarage python3 -c "import sqlite3; sqlite3.connect('/data/mygarage.db').execute('VACUUM')"
  2. Migrate to PostgreSQL (see Database Configuration)

Low Docker Resources

Docker Desktop → Settings → Resources:

  • CPU: Increase to 2+ cores
  • Memory: Increase to 1GB+

Slow Disk (HDD)

Solution: Move /data volume to SSD

Too Many Photos/Documents

Solution:

  • Compress photos before uploading
  • Delete old documents no longer needed
  • Archive old vehicles (moves data out of active queries)

High CPU Usage

Normal: 5-15% idle, 20-40% during OCR processing

If consistently > 60%:

Diagnosis:

# Check what process is using CPU
docker exec mygarage top

Possible Causes:

  • Runaway background job (check logs)
  • Resource-intensive query (check database)
  • Restart container: docker restart mygarage

Fuel Tracking Problems

MPG Not Calculating

Cause: Requires 2+ full tank fill-ups

Solution:

  1. Verify first fill-up has Full Tank Fill-up checked
  2. Add second fill-up with Full Tank Fill-up checked
  3. MPG will calculate on second+ fill-up

MPG Seems Wrong

Too High (e.g., 60 MPG on a truck):

  • Missed fill-up between entries (shows 2x distance on 1 tank)
  • Odometer entry error (typo)
  • Gallons entry error (half the actual amount)

Too Low (e.g., 10 MPG on a sedan):

  • Partial fill mistakenly marked as Full Tank Fill-up
  • Odometer recorded incorrectly

Fix: Edit recent fill-ups to correct data


LiveLink Issues

Device Not Discovered

Symptoms:

  • WiCAN configured but not appearing in MyGarage
  • Device list shows no unlinked devices

Diagnosis:

# Check MyGarage logs for LiveLink messages
docker logs mygarage 2>&1 | grep -i "livelink\|wican\|ingest"

# Test ingestion endpoint directly
curl -X POST https://mygarage.local/api/v1/livelink/ingest \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"autopid_data":{"TEST":1},"config":{},"status":{"device_id":"test123"}}'

Solutions:

Token Mismatch

Cause: WiCAN token doesn't match MyGarage token

Fix:

  1. Go to Settings → Integrations, open the WiCAN tab on the LiveLink card and click WiCAN settings
  2. The token is shown only once, when generated. If you don't have it, click Generate for a new one (the old one stops working)
  3. In WiCAN web UI, set Authorization header to Bearer YOUR_TOKEN (include "Bearer " prefix)

Incorrect Endpoint URL

Cause: WiCAN sending to wrong URL

Fix:

  • Verify URL: https://your-domain/api/v1/livelink/ingest
  • Include /api/v1/livelink/ingest path
  • Use HTTPS if reverse proxy requires it
  • Check for trailing slashes

Network Connectivity

Cause: WiCAN can't reach MyGarage

Fix:

  • Verify WiCAN is connected to WiFi (check device web UI)
  • Ensure WiCAN and MyGarage are on same network (or properly routed)
  • Check firewall rules allow WiCAN to reach MyGarage port
  • Test: curl http://mygarage-ip:8686/health from WiCAN network segment

LiveLink Disabled

Cause: LiveLink integration turned off. While it is off, nothing is stored from any source (WiCAN, Torque or MQTT), no new device is discovered, and SD-card backfill does not run.

Fix:

  • Go to Settings → Integrations and click the LiveLink settings gear on the LiveLink card
  • Turn on Enable LiveLink

No Telemetry Data

Symptoms:

  • Device discovered but no gauges/data on LiveLink tab
  • Charts show no data points

Diagnosis:

# Check for telemetry processing
docker logs mygarage 2>&1 | grep -i "telemetry\|stored"

# Check database for telemetry entries
docker exec mygarage python3 -c "import sqlite3; print(sqlite3.connect('/data/mygarage.db').execute('SELECT COUNT(*) FROM vehicle_telemetry').fetchone()[0])"

Solutions:

Device Not Linked to Vehicle

Cause: Telemetry only stored for linked devices

Fix:

  1. Go to Settings → Integrations and open the device's tab on the LiveLink card
  2. Click its settings button (for example WiCAN settings) and find the device
  3. Use the vehicle dropdown to link it to a vehicle

AutoPID Not Configured

Cause: WiCAN not polling any PIDs

Fix:

  1. Access WiCAN web UI
  2. Go to AutoPID configuration
  3. Add PIDs to poll (use vehicle profile or custom PIDs)
  4. Save and reboot WiCAN

Raw CAN Frames Instead of Decoded Data

Cause: WiCAN publishing raw CAN frames instead of decoded telemetry

Expected format (decoded):

{"odometer": 87458.0, "engine coolant temperature": 91.5}

Wrong format (raw):

{"bus":"0","type":"rx","frame":[{"id":631,"dlc":8,"data":"FF0000010000AAA7"}]}

Fix:

  • In WiCAN AutoPID settings, ensure MQTT/HTTP output uses decoded format
  • Check WiCAN documentation for your firmware version

MQTT Connection Failed

Symptoms:

  • The Mosquitto tab on the LiveLink card says Broker not connected
  • Test fails

Diagnosis:

# Check if broker is reachable
nc -zv 192.168.1.50 1883   # your broker's address

# Check MyGarage logs for MQTT errors
docker logs mygarage 2>&1 | grep -i "mqtt"

# Check broker logs (if using Mosquitto)
docker logs mosquitto

Solutions:

Broker Not Running

Fix:

docker ps | grep mosquitto
# If not running:
docker start mosquitto

Wrong Host/Port

Fix:

  • Verify broker IP address is correct
  • Default port is 1883 (or 8883 for TLS)
  • Use IP address instead of hostname if DNS isn't working

Authentication Failed

Cause: Broker requires username/password

Fix:

  1. Open the Mosquitto tab on the LiveLink card, click Mosquitto settings, and enter Username and Password
  2. Verify credentials match broker configuration
  3. Click Save, then Test (it uses the saved settings)

Firewall Blocking Port

Fix:

# Allow MQTT port
sudo ufw allow 1883/tcp

TLS Mismatch

Cause: Broker requires TLS but MyGarage not configured for it (or vice versa)

Fix:

  • Match TLS setting to broker configuration
  • If broker requires TLS, enable Use TLS/SSL in Mosquitto settings
  • If broker doesn't support TLS, disable Use TLS/SSL

Phantom Devices

Symptoms:

  • Unknown device IDs appear that you don't recognize
  • Devices with similar-but-wrong IDs to your actual device

Cause: MQTT brokers retain messages. When MyGarage subscribes, it receives old retained messages from devices that previously published to the broker.

Solution:

# Stop Mosquitto
docker stop mosquitto

# Remove persistence database
docker run --rm -v /path/to/mosquitto/data:/data alpine rm /data/mosquitto.db

# Start Mosquitto
docker start mosquitto

# Delete phantom devices from MyGarage
# Go to Settings → Integrations, open the source's tab on the LiveLink card,
# click its settings button and delete the phantom devices

Prevention: If switching WiCAN devices or testing different configurations, clear retained messages before connecting new devices.

Drive Sessions Not Recording

Symptoms:

  • Vehicle runs but no drive sessions created
  • Sessions show as one long session

Diagnosis:

# Check for session events
docker logs mygarage 2>&1 | grep -i "session"

# Check ECU status in database
docker exec mygarage python3 -c "import sqlite3; [print(*r) for r in sqlite3.connect('/data/mygarage.db').execute('SELECT device_id, ecu_status, last_seen FROM livelink_devices')]"

Solutions:

No Speed or Odometer MyGarage Recognises

Cause: Since v3.3.0 a drive is recorded only when the vehicle moves: a speed of 5 km/h (about 3 mph) or more, or an odometer reading that goes up. A device that never reports either records no drives, and LiveLink settings shows a warning naming it.

Fix:

  • Add vehicle speed or odometer to the WiCAN's AutoPID list
  • Check the container log for the readings the device actually sends
  • As a last resort, set How drives are detected to By device connection (legacy), which opens a drive whenever the device connects

Drives Split or Merged Wrongly

A drive ends when the vehicle has sat still for Stop before a new drive (default 15 minutes, in LiveLink settings), or when the device has sent nothing for 5 minutes. Movement that comes back inside the stop window carries on the same drive. So a fuel stop stays one drive and a longer stop becomes two: raise Stop before a new drive if your stops get split, lower it if separate trips get merged. Session Grace Period (default 60 seconds) delays ending a drive after WiFi drops. See LiveLink.

Odometer Not Syncing

Symptoms:

  • Telemetry working but odometer not updating
  • No LiveLink badge on odometer entries

Causes:

Vehicle Doesn't Support Odometer PID

Reality: Many vehicles don't expose odometer via standard OBD2 PID (0xA6)

Fix:

  1. Search for manufacturer-specific odometer PIDs for your vehicle
  2. Add custom PID to WiCAN AutoPID configuration
  3. Some vehicles require proprietary PIDs (Honda, Mitsubishi, etc.)

Odometer PID Not Configured

Fix:

  1. Check WiCAN AutoPID configuration
  2. Add odometer PID if not present
  3. Vehicle profiles may or may not include odometer

Device Not Linked

Cause: Odometer sync requires device linked to vehicle

Fix: Link device to vehicle (see Device Not Linked to Vehicle)

Alerts Not Sending

Symptoms:

  • Threshold exceeded but no notification
  • Device offline but no alert

Diagnosis:

# Check alert settings and delivery
docker logs mygarage 2>&1 | grep -i "alert\|notif"

Solutions:

Notification Backend Not Configured

Fix:

  • MyGarage supports ntfy, Gotify, Pushover, Slack, Discord, Telegram, Matrix, and email. Configure at least one under Settings → Notifications and send a test.

Alert Cooldown Active

Cause: 30-minute cooldown prevents repeated alerts

Expected: Same alert won't fire again until cooldown expires

Threshold Not Set

Fix:

  • Alert lines can be set in Settings only for sensors that offer them, such as a propane tank
  • Open its tab on the LiveLink card, click its settings button, and fill Low or Critical under Alerts

Alert Type Disabled

Fix:

  • Check the alert toggles under LiveLink settings (the gear on the LiveLink card)
  • Ensure specific alert type (offline, threshold, firmware) is enabled

Docker Issues

"Permission Denied" Errors

Error: permission denied: '/data/mygarage.db'

Cause: Data directory not writable by container user (UID 1000)

Solution:

# Change ownership
sudo chown -R 1000:1000 ./data

# Or change permissions
chmod -R 755 ./data

Cannot Pull Docker Image

Error: Error response from daemon: Get https://ghcr.io/v2/: unauthorized

Cause: Docker not logged in (if using private registry)

Solution:

# MyGarage is public - no login required
docker pull ghcr.io/homelabforge/mygarage:latest

# If still fails, check internet connection
ping ghcr.io

Docker Compose Command Not Found

Error: docker-compose: command not found

Cause: Docker Compose not installed

Solution:

# Install Docker Compose (Linux)
sudo apt install docker-compose

# Or use `docker compose` (Compose V2)
docker compose up -d

Maintenance Mode and Repair Tools

Added in v3.3.0.

backend/tools/ ships in the runtime image and holds the scripts that repair LiveLink data in place. Before v3.3.0 the directory was built and then discarded, so every one of these commands failed with can't open file.

Maintenance mode. Setting MYGARAGE_MAINTENANCE_MODE=1 starts the instance for migrations only: the scheduler, MQTT subscriber and Telegram fuel commands do not start, the ingest endpoints and the admin SD-card backfill answer 503, and the telemetry writers refuse. The rest of the admin API stays open, so you can watch a repair and turn the mode back off. It exists because these tools have to see the data exactly as a migration left it, before any new reading arrives, and a dongle replaying its buffer mid-repair would corrupt the result.

# add to the service's environment, then restart
MYGARAGE_MAINTENANCE_MODE=1

The tools.

Tool What it does
backfill_livelink_odometer.py Rebuilds odometer records lost to the pre-v3.3.0 units bug, from telemetry already on disk
normalize_telemetry_odometer_units.py Converts stored odometer telemetry to canonical kilometres
fix_session_odometer_units.py Converts drive-session odometers recorded in the wrong unit
recompute_session_aggregates.py Recomputes each session's distance, speed and RPM from the telemetry inside its own window
oidc_allow_relink.py Allows a one-time SSO relink for an account whose identity-provider account was re-created, for up to 30 minutes (--minutes 0 cancels). Writes at once, with no dry run: docker exec -w /app mygarage python tools/oidc_allow_relink.py --username X. See Relinking an SSO Account

Run the four LiveLink tools in that order. The order matters: the backfill reads telemetry as the device reported it, so it has to run before the converters make the history metric.

The dry-run default and exit 2 rules below cover those four tools only.

Each is dry run by default, works against the instance's own configured database (--db only if you need another), supports SQLite and PostgreSQL, and reads from the data whether its work is still outstanding, so running one twice cannot double a value. Where that cannot be decided safely the tool exits 2 rather than guess, and a dry run that refused something exits 2 as well, so a script can gate --apply on it.

Expect recompute_session_aggregates.py to lower old drive distances, often sharply. A session's distance used to be the gap between the vehicle's newest odometer reading at each end, so distance driven while no session was open was charged to whichever session opened next. Your vehicle's mileage is unaffected: odometer records are a separate table and nothing here writes to it.

How far back a repair reaches. All four work from telemetry still on disk, and telemetry is pruned to livelink_telemetry_retention_days (default 90). Anything older is gone. If you want more history repaired, raise that setting and let data age out more slowly before upgrading.

Full detail, including the exact docker exec sequence, is in the v3.3.0 release notes.


Getting More Help

Enable Debug Mode

Temporary Debug:

environment:
  - MYGARAGE_DEBUG=true

Restart and check logs: docker logs mygarage

This variable is the only way to turn on debug logging. The old Debug Mode switch in Settings changed nothing and has been removed.

WARNING: Debug mode:

  • Exposes detailed error messages (may leak internal paths)
  • Disables secure cookie flag (allows HTTP)
  • Never enable in production

Collect Diagnostic Information

When reporting issues, include:

# MyGarage version
docker inspect mygarage | grep "org.opencontainers.image.version"

# Container logs (last 100 lines)
docker logs --tail 100 mygarage

# Container status
docker ps -a | grep mygarage

# Docker Compose config (redact secrets!)
cat docker-compose.yml

# System info
uname -a
docker --version

MyGarage keeps the Telegram bot token, Discord and Slack webhook URLs, and TomTom and Google Places API keys out of its logs. Older versions could write them there, so check older logs before posting them.

Report Issues

  1. Search existing issues: GitHub Issues
  2. If not found, create new issue: Bug Report
  3. Include diagnostic info above

Advanced Troubleshooting

Access MyGarage Container Shell

# Bash shell in running container
docker exec -it mygarage bash

# Check environment variables
env | grep MYGARAGE

# Check file permissions
ls -la /data

Reset MyGarage to Defaults

Complete Reset (WARNING: Deletes all data):

# Stop and remove container
docker-compose down

# Delete data directory
rm -rf ./data

# Recreate
mkdir ./data
sudo chown 1000:1000 ./data

# Start fresh
docker-compose up -d

Restore from Backup

SQLite:

docker-compose stop mygarage
cp data/mygarage-backup.db data/mygarage.db
rm -f data/mygarage.db-wal data/mygarage.db-shm
docker-compose start mygarage

PostgreSQL:

# Restore from SQL dump
docker exec -i mygarage-postgres psql -U mygarage mygarage < backup.sql

Still Having Issues?

Clone this wiki locally