{"record":{"id":"1bb515b7daaab016","repo":"puppeteer/puppeteer","slug":"multiple-deep-combinators-found-in-sequence","errorCode":null,"errorMessage":"Multiple deep combinators found in sequence.","messagePattern":"Multiple deep combinators found in sequence\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/puppeteer-core/src/injected/PQuerySelector.ts","lineNumber":269,"sourceCode":"): AwaitableIterable<Node> {\n  const selectors = JSON.parse(selector) as ComplexPSelectorList;\n  // If there are any empty elements, then this implies the selector has\n  // contiguous combinators (e.g. `>>> >>>>`) or starts/ends with one which we\n  // treat as illegal, similar to existing behavior.\n  if (\n    selectors.some(parts => {\n      let i = 0;\n      return parts.some(parts => {\n        if (typeof parts === 'string') {\n          ++i;\n        } else {\n          i = 0;\n        }\n        return i > 1;\n      });\n    })\n  ) {\n    throw new Error('Multiple deep combinators found in sequence.');\n  }\n\n  return domSort(\n    AsyncIterableUtil.flatMap(selectors, selectorParts => {\n      const query = new PQueryEngine(root, selectorParts);\n      void query.run();\n      return query.elements;\n    }),\n  );\n};\n\n/**\n * Queries the given node for all nodes matching the given text selector.\n *\n * @internal\n */\nexport const pQuerySelector = async function (\n  root: Node,","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/puppeteer/puppeteer/blob/d484e21c17f6023826fefdcdeeb553e04a7aaed8/packages/puppeteer-core/src/injected/PQuerySelector.ts#L251-L287","documentation":"Puppeteer's deep combinator '>>>' (and the P-selector grammar) treats two consecutive deep combinators, or a combinator at the start/end of a selector, as illegal — analogous to CSS rejecting 'a >> >> b'. pQuerySelectorAll parses the selector into a list and flags any run of more than one deep combinator in sequence, throwing this.","triggerScenarios":"Writing a P-selector with '>>> >>>' or '>>>>' (two deep combinators in a row), or one that begins/ends with >>>. Typically from dynamically-built selector strings where fragments concat into '>>> >>>'.","commonSituations":"String-concatenating selector parts without trimming '>>>'; templating engines injecting an empty fragment between two '>>>'; copy-paste from docs that double the combinator.","solutions":["Use exactly one '>>>' between two real selector fragments (e.g. 'div >>> span').","Sanitize generated selectors to collapse/trim repeated '>>>' before passing to $/$$.","Split a multi-level query into separate $() calls instead of chaining deep combinators.","Validate the selector string with a regex like /(^>>>|>>>\\s*$|>>>\\s*>>>)/ before use."],"exampleFix":"// before\nawait page.$('div >>> >>> span');\n\n// after\nawait page.$('div >>> span');","handlingStrategy":"validation","validationCode":"function sanitizePSelector(sel: string): string {\n  // collapse repeated deep combinators and trim leading/trailing >>>\n  let s = sel.replace(/>>>(\\s*>>>)+/g, '>>>').trim();\n  s = s.replace(/(^\\s*>>>\\s+|\\s+>>>\\s*$)/g, '');\n  if (/(>>>\\s*>>>)/.test(s)) throw new Error('Invalid deep combinator sequence');\n  return s;\n}","typeGuard":"const hasValidCombinators = (sel: string): boolean =>\n  !/(^>>>|>>>\\s*$|>>>\\s*>>>)/.test(sel.trim());","tryCatchPattern":"try {\n  await page.$(selector);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Multiple deep combinators found in sequence.') {\n    selector = selector.replace(/>>>\\s*>>>/g, '>>>'); // retry once\n  }\n  throw e;\n}","preventionTips":["Never concatenate selector fragments with a trailing '>>>'.","When building selectors programmatically, trim and dedupe '>>>'.","Prefer splitting complex deep queries into multiple $() calls."],"tags":["selectors","query","deep-combinator","validation"],"backgroundTag":null,"analyzedSha":"d484e21c17f6023826fefdcdeeb553e04a7aaed8","analyzedAt":"2026-08-12T06:33:19.665Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}