Vault KV v2 wrong path (data/ vs metadata/, KV v1 vs v2) in CI
KV version 2 inserts a data/ segment for reads/writes and a metadata/ segment for listing and versions. The vault kv CLI hides this, but raw API calls, policies, and vault-action mappings must include it, or the request 404s or is denied.
What this error means
A curl or vault-action read of secret/ci/app returns "no handler for route" or empty data, while vault kv get secret/ci/app works from the CLI.
$ curl -H "X-Vault-Token: $VAULT_TOKEN" "$VAULT_ADDR/v1/secret/ci/app"
{"errors":["no handler for route \"secret/ci/app\". route entry not found."]}Common causes
The API path omits the data/ segment
On a KV v2 mount, the read endpoint is secret/data/ci/app; hitting secret/ci/app reaches no handler.
Policy or listing uses the wrong segment
Listing needs secret/metadata/...; a policy that only grants on secret/data/... cannot list, and vice versa.
How to fix it
Use data/ to read and metadata/ to list
- For raw API reads/writes, include
data/in the path. - For listing keys, use
metadata/in both the request and the policy. - Let the
vault kvCLI insert these for you when scripting is fine.
# read (API)
curl -H "X-Vault-Token: $VAULT_TOKEN" "$VAULT_ADDR/v1/secret/data/ci/app"
# list (API)
curl -H "X-Vault-Token: $VAULT_TOKEN" \
--request LIST "$VAULT_ADDR/v1/secret/metadata/ci"Write policies against both segments
Grant read on data/ and list on metadata/ so CI can both fetch and enumerate.
path "secret/data/ci/*" { capabilities = ["read"] }
path "secret/metadata/ci/*" { capabilities = ["list"] }How to prevent it
- Remember KV v2 uses data/ (read) and metadata/ (list); KV v1 uses neither.
- Keep policies and raw API paths consistent with the KV version.
- Prefer the
vault kvCLI when you do not want to manage the segment yourself.