{"record":{"id":"0c4dbde0ece5cf28","repo":"pnpm/pnpm","slug":"invalid-query-query-list-can-search-only-by","errorCode":null,"errorMessage":"Invalid query - ${query}. List can search only by version or range","messagePattern":"Invalid query - (.+?)\\. List can search only by version or range","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pnpm11/deps/inspection/tree-builder/src/createPackagesSearcher.ts","lineNumber":61,"sourceCode":"  }\n  if (packageSelector.matchVersion == null) {\n    return true\n  }\n  return !version.startsWith('link:') && packageSelector.matchVersion(version)\n}\n\ninterface ParsedSearchQuery {\n  matchName: (name: string) => boolean\n  matchVersion?: (version: string) => boolean\n}\n\nfunction parseSearchQuery (query: string): ParsedSearchQuery {\n  const parsed = npa(query)\n  if (parsed.raw === parsed.name) {\n    return { matchName: createMatcher(parsed.name) }\n  }\n  if (parsed.type !== 'version' && parsed.type !== 'range') {\n    throw new Error(`Invalid query - ${query}. List can search only by version or range`)\n  }\n  return {\n    matchName: createMatcher(parsed.name),\n    matchVersion: (version: string) => semver.satisfies(version, parsed.fetchSpec),\n  }\n}\n","sourceCodeStart":43,"sourceCodeEnd":68,"githubUrl":"https://github.com/pnpm/pnpm/blob/5b11d3a15b9022a2109cb18ed96a5d652630371f/pnpm11/deps/inspection/tree-builder/src/createPackagesSearcher.ts#L43-L68","documentation":"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).","triggerScenarios":"`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.","commonSituations":"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.","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`"],"exampleFix":"# before\npnpm ls typescript@next\n\n# after\npnpm ls typescript   # or: pnpm ls typescript@5.9.0-beta  (a real version/range)","handlingStrategy":"validation","validationCode":"import npa from 'npm-package-arg'\nimport semver from 'semver'\n\nfunction isSearchableQuery (query: string): boolean {\n  try {\n    const parsed = npa(query)\n    if (parsed.raw === parsed.name) return true           // bare name\n    return parsed.type === 'version' || parsed.type === 'range' // name@semver\n  } catch {\n    return false\n  }\n}\n\nconst queries = params.filter(isSearchableQuery)\nif (queries.length === 0) {\n  throw new Error(`No searchable queries in: ${params.join(', ')}. Use a name or name@semver-range.`)\n}","typeGuard":"function isListSearchQueryError (err: unknown): boolean {\n  // this throw is a plain Error (no PnpmError code) — match on message shape\n  return err instanceof Error && /^Invalid query - .+\\. List can search only by version or range$/.test(err.message)\n}","tryCatchPattern":"catch (err) {\n  if (isListSearchQueryError(err)) {\n    // strip the non-semver suffix and retry with the bare name\n    const bareName = query.split('@')[0]\n    return runList([bareName])\n  }\n  throw err\n}","preventionTips":["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"],"tags":["cli","semver","npm-spec","listing","validation"],"backgroundTag":null,"analyzedSha":"5b11d3a15b9022a2109cb18ed96a5d652630371f","analyzedAt":"2026-08-16T13:18:59.198Z","schemaVersion":2},"datasetVersion":"2026-08-16T18:17:16.020Z"}