Troubleshooting & FAQ
Symptoms, causes, and fixes for the things that trip people up — plus answers to the questions we get most. For exact on-screen messages, see the error reference.
Troubleshooting · App won't load / "Couldn't load data"
| Symptom | Cause & fix |
|---|---|
| "Couldn't load data" panel; tabs are empty | You opened the app from a file:// path. Browsers block the JSON dataset reads there. Serve it over HTTP — e.g. python3 -m http.server 8080 then open http://localhost:8080/app/. |
| Blank page or partial load | A network/CDN hiccup loading fonts or the cloud module. The core app doesn't depend on the cloud module — reload; if datasets 404, confirm the assets/data/*.json files are deployed alongside the app. |
| Everything reset to demo data | Your browser storage for the site was cleared (or you're on a different browser/device). Local data is per-browser. Use Cloud sync (Pro) to carry it across devices. |
Troubleshooting · Sends blocked by the gate
Live send refuses recipients it can't clear. The summary toast reads "N queued, M refused (domain gate)". Here's why a recipient gets refused and how to fix it:
| Reason shown | Meaning | Fix |
|---|---|---|
| domain not authorized for this tenant | The recipient's email domain hasn't been proven for this client. | Verify the domain via DNS-TXT, then resend. |
| invalid recipient | The address has no usable domain. | Fix the roster entry. |
| no allowlist token / token scoped to a different tenant / token scoped to a different domain / allowlist token expired | The scoped, rotating token didn't match this tenant + domain, or it aged out (24h). | Re-run live send so fresh tokens are minted; make sure you're on the correct active client. |
| no notify transport (offline) | You're signed out / offline, so there's no live send channel. | Sign in with the msp entitlement; check connectivity. |
| send failed: … | The notification service returned an error for that recipient. | Retry; the send is idempotent per (campaign, recipient), so retries won't duplicate. |
Troubleshooting · A domain won't verify
If 2 · Verify domain reports "TXT record not found or does not match", work through this checklist:
- Right host. The record must be at
_watchword-verify.<your-domain>. If your DNS UI appends the domain automatically, enter just_watchword-verify. - Exact value. The TXT value must equal the challenge's
watchword-domain-verification=…string verbatim — no extra spaces, no added quotes (your DNS host may add its own quoting; don't double it). - Record type is TXT, not CNAME or A.
- Propagation. DNS changes take time. Wait a couple of minutes (up to an hour with a high TTL), then verify again.
- One challenge at a time. If you re-clicked "Get DNS-TXT challenge", the value changed — publish the latest value.
- Resolver visibility. Verification uses DNS-over-HTTPS, which reads public DNS. The record must be on the public/authoritative zone, not a split-horizon internal-only view.
If lookup itself fails (e.g. "dns lookup failed: …"), it's usually a transient network issue or the host being temporarily unresolvable — retry shortly.
Troubleshooting · A client's data isolation
| Question / symptom | Answer |
|---|---|
| "I ran a campaign but it shows under the wrong client." | Campaigns always target the active client. Switch to the right client in the MSP console before composing. Check the "Active context" line under the tenant tree. |
| "Can one client see another client's recipients?" | No. Only the active client's data is in play, and the cross-client board exposes aggregates only — never recipient rows, emails, or captures. |
| "My training progress disappeared after switching clients." | It didn't — progress is per client. Switch back to the original client and it's there. |
| "Could a signed-in MSP reach a client outside their tree?" | No. Entitlements and tenant access are scoped server-side to the verified session's subtree; out-of-subtree access is refused. |
Troubleshooting · Deliverability
| Question | Answer |
|---|---|
| "My recipients didn't get the simulated email." | Expected — the simulator doesn't send live email. Results are modeled. Live send (when used) routes through the notification service, but the full deliverability stack is deferred. |
| "How do I make sure sims land in the inbox once live send ships?" | The deferred runner will include SPF/DKIM/DMARC setup guidance. Until then, domain authorization (DNS-TXT) is the only sending prerequisite Watchword enforces. |
| "Are open/click numbers real?" | Today they come from the behavioral model. Real open/click webhooks are deferred. |
Troubleshooting · Sync & entitlements
| Symptom | Fix |
|---|---|
| Cloud tab stuck "Loading the optional cloud tier…" | The cloud module isn't deployed or failed to load. The rest of the app works offline — this is normal for local-only runs. |
| "Cloud sync is a Pro feature" | Your account lacks cloud_sync. Upgrade, or use local exports. |
| A Pro feature shows "Locked" you expected unlocked | Entitlements are resolved from your verified session. Confirm you're signed into the right account/tenant; sign out and back in to refresh the entitlement cache. |
| "Nothing in the cloud yet for this tenant" | Pull only works after a push. Sync up for that client first. |
| Synced the wrong client's data | Sync uses the active client. Switch first, then sync — each client uses its own scoped key, so nothing was overwritten. |
| "Live send is an MSP-tier feature" | Live send needs the msp entitlement. |
Frequently asked questions
Do I need an account to use Watchword?
No. The training library and the campaign simulator work fully offline with no account. An account only unlocks the optional cloud tier (sync, MSP/white-label, live send, evidence publishing).
Does Watchword actually send phishing emails?
The simulator does not — it models behavior locally. There is a live-send path that routes through the notification service (gated by domain authorization and the MSP entitlement), but the dedicated mail runner and full deliverability stack are Deferred.
Does Watchword store the passwords people type into fake pages?
Never. Captures are boolean: Watchword records only that data was entered, never the value or length. See Security & privacy.
Where is my data stored?
Locally in your browser by default. Only PII-free summaries and evidence objects leave your machine, and only when you sign in and choose to sync or publish. CSV/JSON exports download to your device.
Can my MSP clients see each other's data?
No. Each client is a fully isolated tenant; the cross-client board shows aggregates only. See Isolation guarantees.
How do I switch between clients?
Click the client in the MSP console's tenant tree (or "Open" on its board row). No re-login. See Switch clients.
What LLM providers does the AI support, and who pays for it?
OpenRouter (recommended), OpenAI, and Anthropic. You bring your own key; your browser calls the provider directly, so you pay your provider and we never see the key or the inference. See AI-generated lures.
Why was my AI generation blocked?
The abuse fence blocks output that looks like a real credential thief (capture forms, password inputs, exfiltration code, "actually steal" instructions), and the brand guard blocks named-brand impersonation unless you toggle "disclosed internal exercise". Rephrase toward a teachable scenario.
How do I prove training for an audit?
Use Program → Reports & exports for the completion CSV, the auditor evidence-pack preview, and the evidence JSON; or publish the evidence object from the Cloud tab. It maps to HIPAA AT, NIST 3.2.x, SOC 2 CC2, PCI 12.6, and ISO A.6.3.
How do I reset everything?
Clear your browser's storage for the site. The app reloads with fresh sample data. (There's no in-app "reset" button — it's intentionally local.)
Which browsers are supported?
Any modern evergreen browser (Chrome, Edge, Firefox, Safari). The app is vanilla JS with no build step and needs JavaScript and localStorage enabled.