pnpm/pnpm · error · Error
Invalid query - ${query}. List can search only by version or
Error message
Invalid query - ${query}. List can search only by version or range What it means
When `pnpm list`/`pnpm why` receives a search query containing an `@`-suffixed spec, createPackagesSearcher parses it with npa and only accepts name-only queries (raw equals name) or specs whose type is a semver version or range. Anything else — a dist-tag, git spec, or protocol — is rejected with this plain Error (note: no PnpmError code, so it is not catchable by error code, only by message).
Source
Thrown at pnpm11/deps/inspection/tree-builder/src/createPackagesSearcher.ts:61
}
if (packageSelector.matchVersion == null) {
return true
}
return !version.startsWith('link:') && packageSelector.matchVersion(version)
}
interface ParsedSearchQuery {
matchName: (name: string) => boolean
matchVersion?: (version: string) => boolean
}
function parseSearchQuery (query: string): ParsedSearchQuery {
const parsed = npa(query)
if (parsed.raw === parsed.name) {
return { matchName: createMatcher(parsed.name) }
}
if (parsed.type !== 'version' && parsed.type !== 'range') {
throw new Error(`Invalid query - ${query}. List can search only by version or range`)
}
return {
matchName: createMatcher(parsed.name),
matchVersion: (version: string) => semver.satisfies(version, parsed.fetchSpec),
}
}
View on GitHub (pinned to 5b11d3a15b)
Solutions
- Search by name only (`pnpm ls lodash`) — tags cannot be searched because installed trees only carry resolved versions
- Use a concrete version or range: `pnpm ls lodash@^4`, `pnpm ls lodash@4.17.21`
- If a script builds the query, only append @range when the suffix parses as semver (see validation snippet)
- Find what a tag resolves to first: `pnpm view <pkg> dist-tags`
Example fix
# before pnpm ls typescript@next # after pnpm ls typescript # or: pnpm ls typescript@5.9.0-beta (a real version/range)
Defensive patterns
Strategy: validation
Validate before calling
import npa from 'npm-package-arg'
import semver from 'semver'
function isSearchableQuery (query: string): boolean {
try {
const parsed = npa(query)
if (parsed.raw === parsed.name) return true // bare name
return parsed.type === 'version' || parsed.type === 'range' // name@semver
} catch {
return false
}
}
const queries = params.filter(isSearchableQuery)
if (queries.length === 0) {
throw new Error(`No searchable queries in: ${params.join(', ')}. Use a name or name@semver-range.`)
} Type guard
function isListSearchQueryError (err: unknown): boolean {
// this throw is a plain Error (no PnpmError code) — match on message shape
return err instanceof Error && /^Invalid query - .+\. List can search only by version or range$/.test(err.message)
} Try / catch
catch (err) {
if (isListSearchQueryError(err)) {
// strip the non-semver suffix and retry with the bare name
const bareName = query.split('@')[0]
return runList([bareName])
}
throw err
} Prevention
- Only append @range to list/why queries when semver.valid or semver.validRange accepts the suffix
- Resolve dist-tags to versions first (`pnpm view <pkg> dist-tags`) before using them in tree filters
- Remember this error has no error code — code-based dispatch will miss it; match the message
When it happens
Trigger: `pnpm ls lodash@next` (dist-tag — npa type is 'tag', not version/range), `pnpm why "pkg@git+https://…"`, `pnpm ls "pkg@file:../x"`, `pnpm ls "pkg@http://…"`. Any name@X where X is not a valid semver version/range hits the throw.
Common situations: Trying to filter the dependency tree by dist-tag the same way you would pin in package.json; pasting a dependency spec straight from package.json (git/file/alias specs) into pnpm ls; scripts that append `@${VERSION}` where VERSION is a tag like 'latest' or empty/garbage producing a non-semver suffix.
Related errors
- INVALID_PACKAGE_NAME
- FINDER_NOT_FOUND
- MISSING_PACKAGE_NAME
- Invalid argument - ${arg}. Rebuild can only select by versio
- APPROVE_BUILDS_ALL_WITH_ARGS
AI-assisted analysis of pnpm/pnpm@5b11d3a15b (2026-08-16).
Data as JSON: /api/errors/0c4dbde0ece5cf28.
Report an issue: GitHub.