{"record":{"id":"46cf413c42f393fa","repo":"jackwener/OpenCLI","slug":"dongchedi-specs-seriesid-no-spec-overview-foun","errorCode":null,"errorMessage":"dongchedi specs ${seriesId}: No spec overview found for this series (layout may have changed).","messagePattern":"dongchedi specs (.+?): No spec overview found for this series \\(layout may have changed\\)\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/dongchedi/specs.js","lineNumber":108,"sourceCode":"    site: 'dongchedi',\n    name: 'specs',\n    access: 'read',\n    aliases: ['config'],\n    description: '懂车帝车系配置概览（尺寸 / 动力 / 发动机 / 变速箱 / 四驱 / 悬挂 / 气囊）',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'series_id', required: true, positional: true, help: '车系 ID（来自 search 的 series_id，或 /auto/series/<id> URL）' },\n    ],\n    columns: SPECS_COLUMNS,\n    func: async (args) => {\n        const seriesId = normalizeSeriesId(args.series_id);\n        const pp = await dcdFetchPageProps(`/auto/series/${seriesId}`, `specs ${seriesId}`);\n        const rows = parseSpecs(pp.overviewData, seriesId);\n        // Every series has at least dimensions/power; an all-empty sheet means\n        // the overview block was absent (layout drift) — don't emit a blank sheet.\n        if (rows.every((r) => r.field === 'series_id' || !r.value)) {\n            throw new CommandExecutionError(\n                `dongchedi specs ${seriesId}`,\n                'No spec overview found for this series (layout may have changed).',\n            );\n        }\n        return rows;\n    },\n});\n","sourceCodeStart":90,"sourceCodeEnd":116,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/dongchedi/specs.js#L90-L116","documentation":"A CommandExecutionError thrown by the dongchedi specs command (clis/dongchedi/specs.js:108). After fetching the series page's `overviewData`, the parser produced only empty rows (nothing beyond the series_id row had a value). Since every real series has at least dimension/power specs, an all-empty sheet means the overview block was missing — i.e. the page layout drifted from what the parser expects — and the library refuses to emit a blank spec sheet.","triggerScenarios":"Calling dongchedi specs with a series_id whose page's `overviewData` is missing, null, or restructured: Dongchedi changed the Next.js pageProps schema for the series page, the series page uses a new template variant, or the SSR payload for that series omits the overview block entirely.","commonSituations":"Scrapers breaking after a silent Dongchedi front-end redeploy; spec queries for obscure/discontinued/newly-added series whose pages use a different template; caching a stale parser against an updated site.","solutions":["Check whether the series page loads normally in a browser and still contains an overview/spec section under `__NEXT_DATA__`.","Inspect the live `props.pageProps.overviewData` shape and update parseSpecs to match the new layout.","Try a different, well-known series_id to confirm the parser works generally (isolating layout drift vs. a bad series).","Retry later — if the site is mid-rollout, some series may temporarily serve the new layout.","Catch CommandExecutionError and surface a clear 'layout changed' message instead of writing an empty spec sheet."],"exampleFix":"// before\nconst rows = parseSpecs(pp.overviewData, seriesId); // throws: layout drift\n// after\nif (pp.overviewData?.specList) {\n  const rows = parseSpecs(pp.overviewData, seriesId); // adapt parser to new key/schema\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":"function hasOverviewData(pp) {\n  return Boolean(pp && pp.overviewData && typeof pp.overviewData === 'object');\n}","tryCatchPattern":"try {\n  const rows = await dcdSpecs(seriesId);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /spec overview/.test(err.message)) {\n    reportLayoutDrift(seriesId); // alert + degrade to empty result\n  } else throw err;\n}","preventionTips":["Pin a known-good series_id in a smoke test to detect layout drift early.","Verify the series page renders specs in a browser before blaming the id.","Handle 'layout changed' as a distinct failure class in monitoring.","Update parseSpecs promptly when the site's pageProps schema changes."],"tags":["layout-drift","parsing","dongchedi","web-scraping"],"backgroundTag":"site-layout-changed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}