Files
2026-07-12 10:17:17 -04:00

3.5 KiB

Common Bugs & Pitfalls

Auth redirect loop (index.html ↔ dashboard.html)

Symptom: Page constantly refreshes between index.html and dashboard.html.

Root cause: index.html line 131 blindly checks localStorage.getItem('pocketbase_auth') — any truthy value (including stale/expired tokens) triggers a redirect to dashboard.html. Dashboard's onAuthStateChanged then detects the invalid token and bounces back to index.html, but the stale token is never cleared from localStorage.

Fix: In every file that redirects unauthenticated users back to index.html, clear the stale token first:

localStorage.removeItem('pocketbase_auth');
window.location.href = 'index.html';

Files that need this: dashboard.js (line 122), appointments.js (line 50), repair-orders.js (line 58).

PocketBase auto-cancellation ("request was auto-cancelled")

Symptom: Creating/updating records fails with "The request was auto-cancelled" or similar abort error.

Root cause: PocketBase SDK auto-cancels requests that share the same requestKey. By default, all create/update calls to the same collection share the same key — a rapid double-click fires two identical requests and the first is aborted.

Fix — two parts:

  1. Disable auto-cancellation in pocketbase.js by passing { requestKey: null } to all mutating PocketBase calls:

    • addDoc: pb.collection(collName).create(pbData, { requestKey: null })
    • updateDoc: pb.collection(collName).update(docId, pbData, { requestKey: null })
    • setDoc: both internal update and create calls need it
  2. Add double-submission guard to form submit handlers — disable the button on first click:

const submitBtn = document.getElementById('submit-create-ro');
if (submitBtn && submitBtn.disabled) return;
if (submitBtn) {
    submitBtn.disabled = true;
    submitBtn.textContent = 'Creating...';
}

Re-enable the button in BOTH the success path (after form clear/collapse) AND the catch block on error. Forgetting the success path leaves the button permanently disabled after a successful submission.

DuckDNS DNS stale / site unreachable

Symptom: "This site can't be reached" when accessing grajmedia.duckdns.org.

Check order:

  1. dig +short grajmedia.duckdns.org — if returns 127.0.0.1, run the DuckDNS updater manually: bash /opt/duckdns/update.sh
  2. The cron job runs every 5 min: */5 * * * * /opt/duckdns/update.sh
  3. /etc/hosts has 127.0.0.1 grajmedia.duckdns.org for local hairpin NAT — this is intentional, not a bug

Dashboard Completed counter shows 0 (ro.status vs ro.workStatus)

Symptom: "Completed: 0" on the dashboard Repair Orders Today card, despite having completed orders today.

Root causes (usually BOTH apply):

  1. Wrong field: Code filters by ro.status === 'completed' but status only stores waiter/drop-off. Must use ro.workStatus === 'completed'.
  2. Completed orders filtered out at source: loadRepairOrders() in dashboard.js removes all completed orders from dashboardData.repairOrders before any counter can see them.

Fix checklist:

  • Replace ALL ro.status === 'completed' with ro.workStatus === 'completed'
  • Replace ALL ro.status === 'picked-up' with ro.workStatus === 'waiting-for-pickup'
  • Remove the completed-filter from loadRepairOrders() so dashboardData.repairOrders contains ALL orders
  • Each consumer then filters by ro.workStatus as needed
  • See references/status-field-confusion.md for the full reference