Relationships
#4415 Vault stores: a standard "secret not found" error that readResource passes through
Opened by hartmantis · 11/5/2026
Problem
An extension can't tell "this secret does not exist" apart from any other vault failure in a way that works with every vault store.
When a resource has sensitive fields, swamp stores them in a vault and keeps ${{ vault.get(...) }} references in the record. If one of those vault keys is later missing, context.readResource() throws whatever error the vault store threw. Some ways this happens:
- the vault config was pointed at a new vault;
- the secret was deleted;
- the secret was written moments ago and the store reads it back late.
Each store words that error differently:
@swamp/1password:1Password CLI error: [ERROR] ... "<item>" isn't an item in the "<vault>" vault. ...- the documented example of a vault store you write yourself:
Secret '<key>' not found in vault '<name>' local_encryption:Secret '<key>' not found in local vault '<name>'
Our case: a behavior caches a login session (sensitive access and refresh tokens) so it doesn't log in on every run. The service allows very few logins (for example 30 per 5 minutes, 300 a day). When the cached session's vault key is missing, the right move is to log in again. When the vault itself is broken (bad token, vault gone, auth failure), the right move is to fail without spending a login, because the new session couldn't be written back anyway.
Today the only way to tell these apart is to match each store's error text. We match @swamp/1password's wording, so the recovery works only for 1Password users. That stops us publishing the extension as one that works with any vault store.
Proposed solution
A standard "secret not found" signal that every vault store raises and that readResource passes through unchanged. For example:
- a
SecretNotFoundErrorclass (or an errorcodesuch as"SECRET_NOT_FOUND") exported for vault stores to throw fromget()when the key does not exist, carrying the vault name and the key; readResource()and vault expression resolution keep it, as the thrown error or as itscause, so an extension can checkerr instanceof SecretNotFoundError(orerr.code);- the shipped stores (
local_encryption,@swamp/1password, …) adopt it, and the vault store guide documents it as the contract forget().
Alternatives considered
- Recover from every
readResourceerror. Spends a login every time the vault itself is broken, and each run then fails when it writes the session back. - Keep a list of known error wordings, one per store. Breaks when a store changes its wording, and never covers stores we haven't seen.
- Give the extension a manual "log in again" input. Useful as an escape hatch, but every user of a vault store we don't recognise hits the failure before learning about it.
Related: #3806 (vault errors on stored references reported as something else) and #3544 (1Password not-found and auth errors mixed up). Both show how much rides on telling vault error kinds apart.
Triaged
Click a lifecycle step above to view its details.
Sign in to post a ripple.