Troubleshooting & FAQ
Quick fixes for the things people actually hit. For the long-form CLI manual, tvault help troubleshooting.
Exit codes
tvault returns meaningful exit codes, so scripts can branch on them:
| Code | Meaning |
|---|---|
0 | Success |
1 | Generic error |
3 | Vault is locked at rest |
4 | Secret or project not found |
5 | Vault not initialized |
6 | Wrong passphrase |
7 | Vault database is in use by another process (e.g. a running tvault run) |
"Vault is locked" / "wrong passphrase"
The vault is encrypted; reads need it unlocked.
- Interactively:
tvault unlock(or just run a command — you'll be prompted). - Non-interactively (CI, scripts, MCP): set
TVAULT_PASSPHRASEin the environment, or pointTVAULT_PASSPHRASE_FILE(oragent.passphrase_file) at a0600env file. See Environment Variables. - Exit code
6means the passphrase was wrong;3means it's locked and no passphrase was available. - A running agent does not satisfy this for a write. It serves reads only, so
set/delete/import/rotatestill need the passphrase — see the next section.
"vault is locked" from a tvault nested inside tvault run
The same command works on its own but fails with exit code 3 inside tvault run (or MCP vault_run_with_secrets), even with the agent running:
tvault set PROBE x -p demo # works
tvault run --only API_KEY -- tvault set PROBE x -p demo # "vault is locked"This is two deliberate boundaries meeting, not a broken socket:
- A launched child inherits no
TVAULT_*variable.tvault runand MCP exec strip every one of them before starting the child, so the parent'sTVAULT_PASSPHRASEnever reaches it. That is what keeps a subprocess from receiving the key to the whole vault when you handed it two values. See Security. - The agent serves reads, not unlocks. It caches the key and answers
get/getall/getselected— it has no write operation and never hands the key out. Soset,delete,import,rotateand friends need the passphrase whether or not an agent is running.
Together: nested reads work (they route through the agent), nested writes do not.
Fixes, best first:
Move the write out of
tvault run. The wrapper exists to inject values into one process; vault administration belongs beside it, not inside it.Give that one child its own credential, explicitly, if it truly must write:
bashtvault run --only API_KEY -- sh -c 'TVAULT_PASSPHRASE=... tvault set PROBE x -p demo'Understand the trade: that child now holds the passphrase to every project and version, which is exactly what
--onlywas narrowing.
"vault not found" / "not initialized"
Exit code 5. Create a vault first:
tvault initBy default the vault lives at ~/.tvault/vault.db (override with --vault or TVAULT_DIR). See Configuration.
The MCP server won't connect
The MCP server (tvault mcp) speaks JSON-RPC over stdio and unlocks the vault at startup — there is no prompt over a pipe.
- "Connection closed" right away → the server couldn't unlock. The host must pass
TVAULT_PASSPHRASEin the server'senv. Use the host's environment controls or a credential-store launcher — see MCP Overview → Before you connect. - After changing the passphrase the cached key is stale → restart your MCP/agent sessions so they reconnect with the new one.
- Tools appear but calls are denied → the Access Policy is gating them (
access_mode,allow_exec, project/secret globs). Check~/.tvault/mcp-policy.yaml.
"vault is locked by another tvault process" (exit code 7)
The on-disk store (bbolt) is single-writer: only one process can hold the database open at a time.
tvault mcp and tvault agent do not block the CLI — they cache only the key and reopen the vault per request, releasing the lock between calls, so set/get/run/import keep working alongside them. A long-running command that holds the database (for example tvault run wrapping a process that never exits) will still block other writers.
If you hit exit code 7 (or doctor reports "in use by another process"), quit the other tvault process that is holding the database and retry. This used to surface as an opaque open bolt db: timeout.
tvault agent says "unix-only"
The local agent is Linux/macOS only — on Windows it returns "unsupported platform". Use the direct CLI or the MCP server instead; both work everywhere.
"project has no recipients"
vault_export_env_encrypted (and tvault seal with no --recipient/.tvault-recipients) seal to the project's current recipients. If none are set, share the project first:
tvault projects share tvault1… # CLI…or use tvault seal --recipient tvault1… / vault_seal_for_recipients with explicit recipients. See Sharing and Committable Secrets.
"identity export refuses to print"
tvault identity export prints a private key, so it refuses to write to a non-terminal (to avoid landing in a captured log). Pipe it deliberately with --force:
tvault identity export ci --force | gh secret set TVAULT_IDENTITY_KEYRotating the passphrase broke my .env.encrypted
tvault key rotate re-wraps the vault keys but invalidates v1 (passphrase-tied) .env.encrypted files. Use the v2, recipient-based format (encrypt-env --recipient / seal), which is KEK-independent and survives rotation. See Committable Secrets.
FAQ
Where is my data? One local bbolt database at ~/.tvault/vault.db (0600), in a 0700 directory. Secret payloads and key material are encrypted; names, timestamps, versions, audit entries, and other operational metadata remain readable to someone who can read the file. Identities, optional config, and the MCP policy live beside it. See Configuration.
I forgot my passphrase — can I recover it? No. There is no escrow or recovery key by design (local-first). Keep a backup of the passphrase (e.g. in a password manager). You can still share/recover projects via identities if you set them up beforehand.
Can an AI agent read my secret values? Yes, if its policy permits the explicit vault_get_secret tool; vault_set_secret can also receive a plaintext value from the client. Prefer metadata search plus vault_run_with_secrets when the value does not need to enter the conversation, and remember that subprocess output redaction is only a safety net. See the MCP safety model and Security.
Is it safe to commit .env.encrypted / .tvault-recipients? Yes — .env.encrypted is ciphertext and .tvault-recipients holds only public keys. Never commit ~/.tvault/, *.key identity files, or a plaintext .env.
Does it work on Windows? The CLI and MCP server: yes (amd64/arm64). The unlock-once agent: no (unix only).
How do I back up the vault? tvault backup <path> copies vault.db without decrypting its records. The matching passphrase restores the complete owner view; a pre-provisioned recipient identity can read only projects shared to it. Operational metadata remains readable, so treat the backup as sensitive. See Key Management.
See also
- CLI Reference — every command, flag, and the exit-code table
- Environment Variables —
TVAULT_PASSPHRASE,TVAULT_DIR, identities - MCP Overview — setup, the launcher pattern, and the safety model
- Security & Threat Model — what is and isn't protected