basecamp/kamal · error · RuntimeError
Could not find #{missing_items.join(", ")} in LastPass
Error message
Could not find #{missing_items.join(", ")} in LastPass What it means
Raised in LastPass#fetch_secrets after `lpass show ... --json` SUCCEEDED: the JSON is parsed into a {fullname => password} map, then `secrets - results.keys` is computed. If any requested name was not returned under an identical key (the item's 'fullname'), the missing list is joined into this RuntimeError. It is a post-fetch completeness check — the failure mode is name mismatch between your secrets list and the returned fullnames, not a CLI failure.
Source
Thrown at lib/kamal/secrets/adapters/last_pass.rb:27
def loggedin?(account)
`lpass status --color never`.strip == "Logged in as #{account}."
end
def fetch_secrets(secrets, from:, account:, session:)
secrets = prefixed_secrets(secrets, from: from)
items = `lpass show #{secrets.map(&:shellescape).join(" ")} --json`
raise RuntimeError, "Could not read #{secrets} from LastPass" unless $?.success?
items = JSON.parse(items)
{}.tap do |results|
items.each do |item|
results[item["fullname"]] = item["password"]
end
if (missing_items = secrets - results.keys).any?
raise RuntimeError, "Could not find #{missing_items.join(", ")} in LastPass"
end
end
end
def check_dependencies!
raise RuntimeError, "LastPass CLI is not installed" unless cli_installed?
end
def cli_installed?
`lpass --version 2> /dev/null`
$?.success?
end
end
View on GitHub (pinned to eee0083b38)
Solutions
- List the exact fullname: `lpass ls --format "%an"` (or plain `lpass ls`) and copy the path-qualified name into your kamal secrets list (e.g. 'Shared-Prod/RAILS_MASTER_KEY').
- If you prefer short names, move the entry to the vault root (no group) in the LastPass UI so its fullname equals the name.
- Use the numeric ID as the requested key — IDs are stable across renames and folder moves.
Example fix
# before secrets: [ "DB_PASSWORD" ] # lives in group 'Prod' # -> RuntimeError: Could not find DB_PASSWORD in LastPass # after: use the fullname as printed by `lpass ls` secrets: [ "Prod/DB_PASSWORD" ]
Defensive patterns
Strategy: validation
Validate before calling
require "open3"
require "json"
def lpass_fullnames(names)
names.map do |n|
out, _err, st = Open3.capture3("lpass", "show", n, "--json")
next nil unless st.success?
items = JSON.parse(out)
items.flat_map { |i| i["fullname"] }
end.compact.flatten
end
missing = names - lpass_fullnames(names)
abort "LastPass fullname mismatch for: #{missing.join(', ')} — use paths from `lpass ls`" if missing.any? Try / catch
begin
secrets = adapter.fetch(names, account: ACCOUNT)
rescue RuntimeError => e
if (m = e.message.match(/Could not find (.+) in LastPass/))
raise "#{m[1]} not returned by lpass: request the path-qualified fullname (see `lpass ls`) or move the entry to vault root"
end
raise
end Prevention
- Reference grouped/shared-folder entries by their full path as printed by `lpass ls` (GroupName/EntryName).
- Use numeric entry IDs in deploy.yml for stability across folder renames.
- After reorganizing the LastPass vault, re-run `lpass ls` and update the secrets list before deploying.
When it happens
Trigger: adapter.fetch([...]) where lpass returns items whose 'fullname' differs from the requested string: entry stored in a group/shared folder has fullname 'GroupName/EntryName' while you requested 'EntryName'; item type mismatch (site URL vs name); duplicates where lpass returns only one match; or requesting a name that exists but whose returned fullname includes a path prefix.
Common situations: Shared-folder or grouped entries referenced by short name; renaming a folder in LastPass so fullnames shift; mixing ID-based and name-based references across team members.
Related errors
- Could not read #{secrets} from LastPass
- Could not read #{secrets} from Doppler
- Could not read #{item_name} from Google Secret Manager
- Failed to login to LastPass
- LastPass CLI is not installed
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/4faf83db7ff24c7b.
Report an issue: GitHub.