{"record":{"id":"a703e5afcd906f17","repo":"jackwener/OpenCLI","slug":"no-attractions-for-query","errorCode":null,"errorMessage":"No attractions for \"${query}\"","messagePattern":"No attractions for \"(.+?)\"","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"info","filePath":"clis/trip/attraction.js","lineNumber":51,"sourceCode":"    columns: [\n        'rank',\n        'name',\n        'rating', 'reviews', 'booked',\n        'price', 'currency',\n        'url',\n    ],\n    func: async (page, kwargs) => {\n        const query = parseKeyword('query', kwargs.query);\n        const limit = parseListLimit(kwargs.limit);\n\n        const searchUrl = buildAttractionSearchUrl(query);\n        await page.goto(searchUrl);\n        const waitResult = await page.evaluate(WAIT_FOR_ATTRACTIONS_JS);\n        if (waitResult === 'captcha') {\n            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');\n        }\n        if (waitResult === 'empty') {\n            throw new EmptyResultError('trip attraction', `No attractions for \"${query}\"`);\n        }\n        if (waitResult !== 'content') {\n            throw new CommandExecutionError(`Trip.com things-to-do page did not render product cards (state=${String(waitResult)})`);\n        }\n        const raw = await page.evaluate(buildAttractionExtractJs());\n        if (!Array.isArray(raw)) {\n            throw new CommandExecutionError('Trip.com attraction DOM extraction returned malformed rows');\n        }\n        if (raw.length === 0) {\n            throw new CommandExecutionError('Trip.com attraction cards rendered but parser did not find required detail-link anchors');\n        }\n        return raw.slice(0, limit).map((r, i) => ({\n            rank: i + 1,\n            name: r.name,\n            rating: r.rating,\n            reviews: r.reviews,\n            booked: r.booked,\n            price: r.price,","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/attraction.js#L33-L69","documentation":"The `trip attraction` command treats a successful page load with zero product cards as a legitimate empty result and throws EmptyResultError scoped to 'trip attraction'. Trip.com rendered fine and no verification was required — the destination keyword simply matched no things-to-do products. It is thrown when WAIT_FOR_ATTRACTIONS_JS resolves to 'empty'.","triggerScenarios":"Calling `trip attraction <query>` when the things-to-do search page for that keyword renders but contains no attraction product cards (waitResult === 'empty'), e.g. misspelled or non-tourist destination keywords.","commonSituations":"Typo'd or overly specific keywords ('Tokio', 'Louvre museum tickets price'); searching a tiny town or non-tourist location with no listed attractions; keyword that matches only hotels/flights, not experiences; Trip.com regional site having no inventory for the destination.","solutions":["Verify and simplify the keyword (e.g. 'Tokyo' instead of a neighborhood or misspelling) and retry.","Try the destination in English, as Trip.com's international things-to-do search matches English names best.","Broaden the query to the nearest major city or region that has attractions listed.","If you expect results for a known destination, complete a Trip.com verification first (region inventory can be gated) and retry."],"exampleFix":"// before\nawait runCli(['trip', 'attraction', 'Tokio']);\n// after: catch EmptyResultError and retry with corrected keyword\ntry {\n  await runCli(['trip', 'attraction', rawQuery]);\n} catch (e) {\n  if (e.name === 'EmptyResultError') return runCli(['trip', 'attraction', correctedKeyword]);\n  throw e;\n}","handlingStrategy":"fallback","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  return await runCli(['trip', 'attraction', query]);\n} catch (e) {\n  if (e.name === 'EmptyResultError') {\n    return []; // no attractions for this keyword\n  }\n  throw e;\n}","preventionTips":["Use canonical English destination names ('Tokyo', 'Paris') as the query.","Validate user-supplied keywords against a city list before calling the command.","Normalize/trim input and avoid neighborhood-level or ticket-specific phrasing.","Provide a UI fallback message when a keyword returns zero attractions."],"tags":["empty-result","no-data","scraping","trip-com"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}