Repository navigation
Troubleshooting
Comprehensive troubleshooting for common MyGarage issues, organized by category.
- Installation Issues
- Authentication Problems
- Database Issues
- VIN Decoder Errors
- File Upload Problems
- OCR Issues
- Reverse Proxy Problems
- Performance Issues
- Fuel Tracking Problems
- LiveLink Issues
- Docker Issues
- Maintenance Mode and Repair Tools
Symptoms:
-
docker psdoesn'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 mygarageCommon Causes & Solutions:
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 insteadOr find what's using port 8686:
sudo lsof -i :8686
# Kill the process or change MyGarage portError: 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 ./dataError: FATAL: password authentication failed for user "mygarage"
Fix:
- Verify
POSTGRES_PASSWORDmatchesMYGARAGE_DATABASE_URL - Ensure PostgreSQL container is running:
docker ps | grep postgres - Check PostgreSQL logs:
docker logs mygarage-postgres - Reset password:
docker exec mygarage-postgres psql -U postgres -c "ALTER USER mygarage WITH PASSWORD 'new-password';"
Symptoms:
- Container is running but http://localhost:8686 doesn't load
- "Connection refused" error in browser
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 mygarageSolutions:
# 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 --reloadIf accessing from another device:
- Don't use
localhost- use server IP (e.g.,http://192.168.1.100:8686) - Verify server IP:
ip addr showorifconfig
# Restart Docker networking
docker-compose down
docker-compose up -dMyGarage 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.dbReport the failing migration and error on GitHub, then restore from backup if needed.
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.
Symptoms:
-
bun: command not foundwhen trying to runbun installorbun 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 higherError: 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 --forceSymptoms:
- 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 typosSymptoms:
- 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:3000Fixes:
1. Clear Vite cache:
rm -rf node_modules/.vite
bun dev2. Hard refresh browser:
- Chrome/Firefox/Edge:
Ctrl+Shift+R(Windows/Linux) orCmd+Shift+R(Mac) - Safari:
Cmd+Option+R
3. Restart dev server:
# Stop server (Ctrl+C), then:
bun dev4. 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 connectionsError: 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 lintError: 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:runSymptoms:
-
bun installtaking >30 seconds -
bun devslow 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_modulesFixes:
- Upgrade Bun to latest:
bun upgrade - Exclude
node_modulesfrom antivirus scans - Use SSD instead of HDD for development
- Close resource-intensive applications
Scenario: Only user, forgot password, can't login
Solutions:
docker-compose stop mygarage
rm data/mygarage.db
docker-compose start mygarage
# Re-register at web interfacedocker-compose stop mygarage
cp data/mygarage-backup.db data/mygarage.db
rm -f data/mygarage.db-wal data/mygarage.db-shm
docker-compose start mygarageSettings 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.
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"
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 mygarageA 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:
- Copy the Redirect URI from MyGarage (Settings → System → OIDC section)
- Add this exact URI to your OIDC provider's allowed redirect URIs
- Ensure you don't mix http/https
- The path should end with
/auth/oidc/callback
Error: OIDC claims missing email in the log
Cause: OIDC provider not returning email
Fix:
- Ensure
emailscope is requested - Configure OIDC provider to include
emailin ID token claims - Check OIDC provider documentation for claim configuration
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.
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 mygarageError: 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-postgresSolutions:
docker-compose up -d postgres
# Wait for PostgreSQL to fully start (check logs)
docker-compose up -d mygarage# Verify hostname matches container name
environment:
- MYGARAGE_DATABASE_URL=postgresql+asyncpg://user:pass@mygarage-postgres:5432/mygarage
# ^^^^^^^^^^^^^^^^
# Must match container name# Ensure containers are on same network
docker network inspect mygarage_default
# Look for both containersCauses:
- 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)
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
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.
Error: 503 Service Unavailable or timeout
Cause: NHTSA vPIC API is down or slow
Solutions:
- Wait 5-10 minutes and try again
- Use manual entry
- Check NHTSA API status: https://vpic.nhtsa.dot.gov/api/
Diagnosis:
# Check container logs
docker logs mygarage | grep -i "upload\|error"
# Check disk space
df -h | grep /srv/raid0Common Causes:
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
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 diskSolution:
- Use wired connection instead of Wi-Fi
- Compress files before uploading
- Upload one file at a time
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 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).
Possible Causes:
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)
Expected Behavior: OCR reads typed text, not handwriting
Solution: Fill in the form by hand
Current Limitation: OCR is configured for English only
Workaround: Fill in the form by hand
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
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+)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.logSolutions:
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
# ...
}If reverse proxy is in Docker, ensure same network:
networks:
- traefik-proxy # Both reverse proxy and MyGarage must be on this networkCause: 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
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 traefikCommon Issues:
Domain Not Resolving:
# Verify DNS
nslookup garage.example.com
# Ensure A record points to your server IPPort 80 Not Open (required for Let's Encrypt HTTP challenge):
sudo ufw allow 80/tcpRate Limit Hit:
- Let's Encrypt allows 50 certs per domain per week
- Use staging environment for testing
- Wait 7 days for limit reset
Cause: Using Let's Encrypt staging certificates
Solution: Switch to production:
Certbot:
sudo certbot --nginx -d garage.example.com # Remove --staging flagTraefik:
# Remove staging certificatesResolvers config
certificatesResolvers:
letsencrypt:
acme:
# caServer: https://acme-staging-v02.api.letsencrypt.org/directory # Remove this lineDiagnosis:
# Check resource usage
docker stats mygarage
# Check database size
ls -lh data/mygarage.dbCommon Causes & Solutions:
If > 500MB or > 10,000 records:
- Vacuum database:
docker exec mygarage python3 -c "import sqlite3; sqlite3.connect('/data/mygarage.db').execute('VACUUM')"
- Migrate to PostgreSQL (see Database Configuration)
Docker Desktop → Settings → Resources:
- CPU: Increase to 2+ cores
- Memory: Increase to 1GB+
Solution: Move /data volume to SSD
Solution:
- Compress photos before uploading
- Delete old documents no longer needed
- Archive old vehicles (moves data out of active queries)
Normal: 5-15% idle, 20-40% during OCR processing
If consistently > 60%:
Diagnosis:
# Check what process is using CPU
docker exec mygarage topPossible Causes:
- Runaway background job (check logs)
- Resource-intensive query (check database)
- Restart container:
docker restart mygarage
Cause: Requires 2+ full tank fill-ups
Solution:
- Verify first fill-up has Full Tank Fill-up checked
- Add second fill-up with Full Tank Fill-up checked
- MPG will calculate on second+ fill-up
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
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:
Cause: WiCAN token doesn't match MyGarage token
Fix:
- Go to Settings → Integrations, open the WiCAN tab on the LiveLink card and click WiCAN settings
- 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)
- In WiCAN web UI, set Authorization header to
Bearer YOUR_TOKEN(include "Bearer " prefix)
Cause: WiCAN sending to wrong URL
Fix:
- Verify URL:
https://your-domain/api/v1/livelink/ingest - Include
/api/v1/livelink/ingestpath - Use HTTPS if reverse proxy requires it
- Check for trailing slashes
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/healthfrom WiCAN network segment
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
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:
Cause: Telemetry only stored for linked devices
Fix:
- Go to Settings → Integrations and open the device's tab on the LiveLink card
- Click its settings button (for example WiCAN settings) and find the device
- Use the vehicle dropdown to link it to a vehicle
Cause: WiCAN not polling any PIDs
Fix:
- Access WiCAN web UI
- Go to AutoPID configuration
- Add PIDs to poll (use vehicle profile or custom PIDs)
- Save and reboot WiCAN
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
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 mosquittoSolutions:
Fix:
docker ps | grep mosquitto
# If not running:
docker start mosquittoFix:
- 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
Cause: Broker requires username/password
Fix:
- Open the Mosquitto tab on the LiveLink card, click Mosquitto settings, and enter Username and Password
- Verify credentials match broker configuration
- Click Save, then Test (it uses the saved settings)
Fix:
# Allow MQTT port
sudo ufw allow 1883/tcpCause: 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
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 devicesPrevention: If switching WiCAN devices or testing different configurations, clear retained messages before connecting new devices.
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:
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
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.
Symptoms:
- Telemetry working but odometer not updating
- No LiveLink badge on odometer entries
Causes:
Reality: Many vehicles don't expose odometer via standard OBD2 PID (0xA6)
Fix:
- Search for manufacturer-specific odometer PIDs for your vehicle
- Add custom PID to WiCAN AutoPID configuration
- Some vehicles require proprietary PIDs (Honda, Mitsubishi, etc.)
Fix:
- Check WiCAN AutoPID configuration
- Add odometer PID if not present
- Vehicle profiles may or may not include odometer
Cause: Odometer sync requires device linked to vehicle
Fix: Link device to vehicle (see Device Not Linked to Vehicle)
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:
Fix:
- MyGarage supports ntfy, Gotify, Pushover, Slack, Discord, Telegram, Matrix, and email. Configure at least one under Settings → Notifications and send a test.
Cause: 30-minute cooldown prevents repeated alerts
Expected: Same alert won't fire again until cooldown expires
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
Fix:
- Check the alert toggles under LiveLink settings (the gear on the LiveLink card)
- Ensure specific alert type (offline, threshold, firmware) is enabled
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 ./dataError: 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.ioError: 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 -dAdded 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.
Temporary Debug:
environment:
- MYGARAGE_DEBUG=trueRestart 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
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 --versionMyGarage 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.
- Search existing issues: GitHub Issues
- If not found, create new issue: Bug Report
- Include diagnostic info above
# Bash shell in running container
docker exec -it mygarage bash
# Check environment variables
env | grep MYGARAGE
# Check file permissions
ls -la /dataComplete 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 -dSQLite:
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 mygaragePostgreSQL:
# Restore from SQL dump
docker exec -i mygarage-postgres psql -U mygarage mygarage < backup.sqlStill Having Issues?
- Community Help: GitHub Discussions
- Check FAQ: FAQ
- Report Bugs: GitHub Issues
- Security Issues: Security Advisories