-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Last updated: March 12, 2026
Common issues and solutions for PERTI.
Symptoms: Connection refused, access denied
Solutions:
- Verify MySQL is running
- Check credentials in
load/config.php - Confirm database exists
- Check firewall rules
Symptoms: Connection timeout, login failed
Solutions:
- Verify
ADL_*constants in config - Check Azure SQL firewall allows your IP
- Confirm
pdo_sqlsrvextension is loaded - Test connection string separately
Symptoms: PostGIS spatial queries fail, boundary detection daemon reports errors, get_conn_gis() returns null
Solutions:
- Confirm the
pdo_pgsqlPHP extension is loaded (php -m | grep pgsql) - Verify
GIS_HOST,GIS_DB,GIS_USER, andGIS_PASSconstants are set inload/config.php - Check that the PostgreSQL firewall on Azure allows your IP (or the App Service outbound IPs)
- Test connectivity directly:
If this query fails, PostGIS is not installed or the extension is not enabled on the database.
SELECT PostGIS_Version(); - On Azure, ensure the
postgisextension is listed under Server parameters > azure.extensions for the PostgreSQL Flexible Server.
Symptoms: HTTP 500 on API endpoints that previously worked, null connection errors in logs (Call to a member function on null), endpoints returning empty or broken data silently
Cause: The file defines PERTI_MYSQL_ONLY before including connect.php, which skips all five Azure SQL connections ($conn_adl, $conn_tmi, $conn_swim, $conn_ref, $conn_gis). If the endpoint then uses any of those connections, they are null.
Solutions:
- Identify the affected file and check whether it uses Azure SQL connections:
grep -n 'conn_adl\|conn_tmi\|conn_swim\|conn_ref\|conn_gis' path/to/file.php - If any matches are found, remove the
define('PERTI_MYSQL_ONLY', true);line from that file. - Always grep for Azure SQL connection usage before adding the
PERTI_MYSQL_ONLYflag to any file.
Known files that must NOT use this flag:
-
api/mgt/config_data/(bulk, post, update, delete) -- uses$conn_adl -
api/mgt/tmi/reroutes/,api/mgt/tmi/airport_configs.php-- uses$conn_adl,$conn_tmi -
api/mgt/sua/-- uses$conn_adl -
api/data/configs.php,api/data/tmi/reroute.php,api/data/sua/,api/data/rate_history.php,api/data/weather_impacts.php-- uses$conn_adl
Symptoms: Redirect loop, invalid state
Solutions:
- Verify
VATSIM_REDIRECT_URImatches exactly - Check VATSIM Connect app configuration
- Clear cookies and try again
Symptoms: Logged out mid-session
Solutions:
- Check session storage permissions
- Verify
SESSION_PATHis writable - Check PHP session settings
Symptoms: Lock file error
Solutions:
# Check for running process
ps aux | grep vatsim_adl
# Remove stale lock if process not running
rm scripts/vatsim_adl.lockSymptoms: SP execution > 10 seconds
Solutions:
- Check index health
- Review query execution plans
- Consider history table cleanup
Symptoms: Route parsing stops, parse_queue_gis_daemon.php logs PostGIS connection failures, flights stuck in adl_parse_queue with status pending
Solutions:
- Verify PostGIS is reachable (see PostgreSQL/PostGIS Connection Issues above)
- Check that
nav_fixes,airways, andairway_segmentstables are populated inVATSIM_GIS - Review the parse queue for stuck entries:
SELECT status, COUNT(*) FROM adl_parse_queue GROUP BY status;
- If entries are stuck with high
attemptscounts, check the daemon log for specific SQL errors
Symptoms: boundary_gis_daemon.php runs but flights show no current_artcc or current_tracon, adl_flight_core.boundary_updated_at never updates
Solutions:
- Confirm
artcc_boundariesandtracon_boundariestables inVATSIM_GISare populated:SELECT COUNT(*) FROM artcc_boundaries; SELECT COUNT(*) FROM tracon_boundaries;
- If empty, run the boundary import migration or
scripts/build_sector_boundaries.py - Check that the
geomcolumns contain valid geometries (ST_IsValid(geom)) - Verify
adl_boundary_gridis populated for fast lookups
Symptoms: swim_sync_daemon.php reports errors, swim_flights table stale, SWIM API returning outdated data
Solutions:
- Verify both
get_conn_adl()andget_conn_swim()return valid connections - Check
SWIM_APIdatabase is accessible andswim_flightstable exists - Review the sync daemon log for specific SQL errors or timeout messages
- Compare record counts between source and destination:
-- ADL side SELECT COUNT(*) FROM adl_flight_core WHERE is_active = 1; -- SWIM side (run against SWIM_API) SELECT COUNT(*) FROM swim_flights WHERE is_active = 1;
Symptoms: TMI advisories not posting to Discord, tmi_discord_posts table has rows with status = 'pending' that never clear
Solutions:
- Verify
scripts/tmi/process_discord_queue.phpis running (ps aux | grep process_discord_queue) - Check Discord bot token and webhook URLs are valid in config
- Look for rate-limit entries in
discord_rate_limitstable - Check the daemon log for HTTP 429 (rate limited) or 401 (unauthorized) responses
- If the queue is very backlogged, check
retry_count-- entries with high retry counts may have permanent errors
Symptoms: Trajectory tables growing unbounded, adl_flight_trajectory very large, archival not running
Solutions:
- The archival daemon (
scripts/archival_daemon.php) runs on a 1-4 hour cycle with daily archive at 10:00Z - Verify the daemon is running and check its log for errors
- Check
adl_archive_configfor current retention settings - Review
adl_archive_logfor the last successful run:SELECT TOP 5 * FROM adl_archive_log ORDER BY run_utc DESC;
- If trajectory tables are very large, a manual archive run may be needed
All daemons write to log files that can be checked for errors and status:
| Environment | Log Location |
|---|---|
| Azure App Service | /home/LogFiles/<daemon>.log |
| Local development |
scripts/<daemon>.log (same directory as the daemon script) |
To tail a daemon log on Azure:
# Via Kudu SSH
tail -f /home/LogFiles/vatsim_adl_daemon.logFull daemon list and their intervals are documented in Daemons and Scripts.
Symptoms: Blank map area
Solutions:
- Verify JavaScript enabled
- Check browser console for errors
- Confirm WebGL support
- Try different browser
Symptoms: Stale positions
Solutions:
- Verify ADL daemon is running
- Check VATSIM API status
- Review daemon logs for errors
Symptoms: Untranslated keys showing as [missing: key.name] in the UI
Solutions:
- Verify the i18n scripts are loaded in the correct order on the page:
-
assets/js/lib/i18n.js(core translation module) -
assets/locales/index.js(locale loader and initializer) -
assets/locales/en-US.json(translation dictionary, loaded by the locale loader)
-
- Check that the missing key exists in
assets/locales/en-US.json-- keys use dot notation (e.g.,dialog.confirmDelete.title) - Open the browser console and look for i18n initialization errors
- Verify the locale JSON file loaded successfully (check the Network tab for a failed request to
en-US.json)
Symptoms: Wrong locale detected, UI showing unexpected language behavior
Solutions:
- Force a specific locale via URL parameter:
?locale=en-US - Check
localStoragefor a stored override:localStorage.getItem('PERTI_LOCALE') - Check
navigator.languagein the browser console to see what the browser reports - Locale detection priority: URL param >
localStorage.PERTI_LOCALE>navigator.language>en-USfallback
Symptoms: Flow cone not rendering on the map, measurement points missing or misplaced, compliance analysis panel empty
Solutions:
- Verify
assets/js/tmi_compliance.jsis loaded on the page (check the Network tab or page source) - Check that the PostGIS (
VATSIM_GIS) database is accessible -- flow cone geometry relies on fix positions fromnav_fixes - Confirm
nav_fixestable in GIS database is populated:SELECT COUNT(*) FROM nav_fixes;
- Check the browser console for JavaScript errors from
tmi_compliance.js - Verify the TMI program has an active
ctl_elementthat maps to a valid airport or fix - If measurement points display but flow cones do not, the issue is likely in the JS enhancement layer (approach bearings, centerline calculation) -- check console for geometry errors
Symptoms: Facility flow layers not showing on the NOD map, TMI cards not appearing in the sidebar, NAT tracks missing
Solutions:
- Check that
facility_flow_configstable has entries for the facility being viewed - Verify FEA (Flow Evaluation Area) API connectivity -- check browser Network tab for failed API requests
- Open browser console and look for MapLibre GL errors (layer/source failures)
- For missing NAT tracks, check the
api/nod/tracks.phpendpoint directly to confirm data is being returned - Verify
nod.jsandnod-demand-layer.jsare loaded on the page - Check that MapLibre GL JS is loaded from CDN without errors
Symptoms: All authenticated pages redirect to /hibernation instead of loading normally. Public pages also redirect.
Cause: The system is in hibernation mode. This is intentional behavior when HIBERNATION_MODE is enabled.
Solutions:
- Check
HIBERNATION_MODEinload/config.php-- if set totrue, the system is hibernated - Check the
HIBERNATION_MODEAzure App Setting -- must be set to0(not"false") to disable -
Important: The string
"false"is truthy in PHP. Use0or delete the App Setting entirely to exit hibernation - Follow the full exit procedure in
docs/HIBERNATION_RUNBOOK.mdto properly restore all services - Note that
review.phpis exempted from the redirect and remains accessible during hibernation
Symptoms: All SWIM API endpoints return HTTP 503 (Service Unavailable). API consumers report connection failures.
Cause: The SWIM API intentionally returns 503 during hibernation mode. This is expected behavior, not an error.
Solutions:
- Confirm the system is in hibernation mode (check
HIBERNATION_MODEconfig) - Exit hibernation to restore API access -- follow
docs/HIBERNATION_RUNBOOK.md - Notify API consumers that the service is temporarily suspended
- After exiting hibernation, verify API access at
/api/swim/v1/health.php
Symptoms: The hibernation recovery backfill script (_backfill_full.php) appears stuck on a phase. Status URL shows no progress over extended periods.
Solutions:
- Verify the restart loop is running. The backfill requires periodic HTTP requests to advance:
for i in $(seq 1 24000); do curl -s --max-time 120 "https://perti.vatcscc.org/_backfill_full.php?action=run" -o /dev/null sleep 5 done
- Check the current phase and progress via the status URL:
https://perti.vatcscc.org/_backfill_full.php?action=status - PostGIS on B1ms tier processes approximately 108 flights/minute -- phases with large flight counts take time
- After uploading a new script version via VFS API, OPcache revalidates every 60 seconds -- wait at least 65 seconds before hitting the updated script
- Check the log URL for error messages:
https://perti.vatcscc.org/_backfill_full.php?action=log - Backfill state is stored in MySQL (
backfill_state/backfill_logtables), not in/tmp, so it persists across PHP-FPM restarts
Solutions:
- Check database query times
- Review network latency
- Consider caching
- Check server resources
- Maintenance - Routine tasks
- Configuration - Setup options
- Daemons and Scripts - Background processes
PERTI - Virtual Air Traffic Control System Command Center Production Site | GitHub | Report Issue
Last updated: 2026-02-25
Home Navigation Helper (NEW)
Comprehensive Guides
Getting Started
Architecture
Algorithms & Processing
- Algorithms Overview
- Algorithm ETA Calculation
- Algorithm Trajectory Tiering
- Algorithm Zone Detection
- Algorithm Route Parsing
- Algorithm Data Refresh
SWIM API (Public/External)
- SWIM API
- SWIM Routes API
- SWIM Playbook API
- SWIM Route Data Integration
- Building Route Processing
- CDM Connector Guide
PERTI API (Internal)
Features
Walkthroughs
Operations
Development
Analysis
- Analysis (index)
- ETA Accuracy (Jan-Mar 2026)
Reference