# Troubleshooting

Common errors and fixes. Operator-focused.

## 1. "auth: setup already completed"

You tried to call `setupAdmin()` twice. There is one admin. Use the
recovery phrase to reset the password instead — see
`auth/SECURITY.md`.

## 2. Storage adapter throws "localStorage is not available"

You are running in a Node.js context (not a browser). For tests, set
the adapter manually:

```js
import { MemoryStorageAdapter, setStorageAdapter } from './cms/index.js';
setStorageAdapter(new MemoryStorageAdapter());
```

In a browser, the default adapter localizes automatically — you should
not see this error.

## 3. "Invalid URL: http://192.168..." when adding an image

You tried to use a local network URL. The URL allowlist blocks private
IPs (`10.x`, `172.16-31.x`, `192.168.x`, `169.254.x`) to defend against
SSRF. Use a public CDN URL or self-host the image and reference it by
hostname.

## 4. Backup envelope includes auth payload

Either you exported with a custom key list, or someone patched
`backups-keys.js`. Recover by exporting with the default
`exportBackup()` — auth is auto-excluded. Verify with
`grep cms:admin:auth cms/backups.js` — only the AUTH_KEY constant
should appear (used to reject). See SEC14 in `tests/test-security-source.js`.

## 5. Activity log says "validation failed: missing required field"

The record passed HTML validation but failed schema validation. Open the
record's schema in `schemas/{id}.js` and check which fields are
`required: true`. Required fields must be present in the record before
save.

## 6. PBKDF2 takes 5+ seconds on a slow device

PBKDF2-SHA256 at 310 000 iterations is intentionally slow — it makes
brute-force attacks expensive. On 2018-era mobile devices this can take
~700 ms per login. The lockout after 5 failed attempts + the slow hash
is the layered defense. If a specific device is too slow, see
TRACK-6-PBKDF2-ADAPT in the Track 5 report.

## 7. "Format unsupported: formatVersion=2"

You are trying to import an envelope from a newer CMS. The current
parser only accepts `formatVersion: 1`. Either upgrade both sites to
the same CMS version, or ask the maintainer to add a forward-compatible
reader.

## 8. CSP violation in DevTools: "Refused to execute inline script"

The admin uses `'unsafe-inline'` in its CSP for the embedded
`onclick` handlers. If your site CSP is stricter than the admin's,
inline handlers may be blocked. Either relax the CSP for the
`/admin/*` route or migrate the inline handlers to
`addEventListener` (Track 6 work, see TRACK-6-CSP).

## 9. localStorage quota exceeded

Browser localStorage is typically capped at 5 MB. If you hit the cap:
1. Reduce the activity log size (clearActivity() in DevTools console).
2. Export and rotate auto-backups.
3. Move older records to a separate archive.

For larger datasets, plan the v2.0 IndexedDB adapter migration.

## 10. Editor form does not save my changes

Possible causes:
- Validation error: the form shows a red alert at the top. Read it.
- Schema mismatch: the schema's storage key does not match the
  registered one. Check `cms:admin:{schemaId}` in localStorage.
- Cascade reference: deleting a record blocked because of FK refs.
  Open the cascade warning, confirm or remove dependents first.

## See also

- `SECURITY.md` — security checklist
- `MIGRATION.md` — recipe for common CMS migrations
- `docs/FAQ.md` — common questions
- `auth/SECURITY.md` — auth-specific troubleshooting
