{"record":{"id":"8aff7a7e2684ef4d","repo":"microsoft/playwright-mcp","slug":"config-type-not-found-in-config-d-ts","errorCode":null,"errorMessage":"Config type not found in config.d.ts","messagePattern":"Config type not found in config\\.d\\.ts","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"update-readme.js","lineNumber":225,"sourceCode":"\n  const startMarker = `<!--- Options generated by ${path.basename(__filename)} -->`;\n  const endMarker = `<!--- End of options generated section -->`;\n  return updateSection(content, startMarker, endMarker, table);\n}\n\n/**\n * @param {string} content\n * @returns {Promise<string>}\n */\nasync function updateConfig(content) {\n  console.log('Updating config schema from config.d.ts...');\n  const configPath = path.join(__dirname, 'config.d.ts');\n  const configContent = await fs.promises.readFile(configPath, 'utf-8');\n\n  // Extract the Config type definition\n  const configTypeMatch = configContent.match(/export type Config = (\\{[\\s\\S]*?\\n\\});/);\n  if (!configTypeMatch)\n    throw new Error('Config type not found in config.d.ts');\n\n  const configType = configTypeMatch[1]; // Use capture group to get just the object definition\n\n  const startMarker = `<!--- Config generated by ${path.basename(__filename)} -->`;\n  const endMarker = `<!--- End of config generated section -->`;\n  return updateSection(content, startMarker, endMarker, [\n    '```typescript',\n    configType,\n    '```',\n  ]);\n}\n\nasync function updateReadme() {\n  const readmePath = path.join(__dirname, 'README.md');\n  const readmeContent = await fs.promises.readFile(readmePath, 'utf-8');\n  const withTools = await updateTools(readmeContent);\n  const withOptions = await updateOptions(withTools);\n  const withConfig = await updateConfig(withOptions);","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/microsoft/playwright-mcp/blob/16cf228d7b02c07f800ec3423f471ec2a42d22a9/update-readme.js#L207-L243","documentation":"update-readme.js embeds the user-facing Config type into README.md by reading `config.d.ts` (the published type definitions) and regex-extracting the `export type Config = { ... };` declaration. If that regex fails to match — because the declaration moved, was renamed, or its formatting changed — the script throws rather than generating an empty config section. It is a fragile-by-design check that surfaces drift between the script's expectations and the generated .d.ts bundle.","triggerScenarios":"Running `node utils/update-readme.js` when config.d.ts no longer contains a literal `export type Config = {` ... `};` block — e.g. the type was renamed, extracted into an imported interface, made to extend another type, or the file wasn't regenerated after source changes so config.d.ts is missing or stale. The non-greedy regex `/(\\{[\\s\\S]*?\\n\\});/` also fails if the closing brace is not at the start of a line (e.g. minified or differently formatted output).","commonSituations":"Refactoring src/config.ts so Config becomes an interface or a union; regenerating config.d.ts with a newer TypeScript compiler that formats the emitted declaration differently (e.g. `export type Config = { ... } & SharedOptions;`); running the script on a fresh clone before `npm run build` has produced config.d.ts; declaration emit bundling (api-extractor/dts-bundle) reordering or annotating the block with comments that break the `\\n});` anchor.","solutions":["Regenerate the type definitions first (`npm run build` or whatever produces config.d.ts in utils/), then rerun `node utils/update-readme.js`.","Inspect config.d.ts and confirm it still contains `export type Config = {` with the closing `};` on its own line; if the declaration shape changed (interface, intersection, union), update the regex in updateConfig (update-readme.js:~222) to match the new form.","If Config was legitimately restructured, either restore a self-contained object literal type in the emitted d.ts or extend the extraction logic to handle the new syntax before rerunning the script."],"exampleFix":"// before (config.d.ts) — closing brace not on its own line breaks the regex\nexport type Config = { browser: { launchOptions?: LaunchOptions } };\n\n// after\nexport type Config = {\n  browser: {\n    launchOptions?: LaunchOptions;\n  };\n};","handlingStrategy":"validation","validationCode":"// Check the d.ts still exposes the expected declaration shape before generating:\nimport fs from 'fs';\n\nconst dts = fs.readFileSync('utils/config.d.ts', 'utf-8');\nif (!/export type Config = (\\{[\\s\\S]*?\\n\\});/.test(dts)) {\n  console.error('config.d.ts no longer contains a matchable `export type Config = { ... };` block — regenerate types or update the extraction regex.');\n  process.exit(1);\n}","typeGuard":"function hasExtractableConfigType(dtsContent) {\n  return /export type Config = (\\{[\\s\\S]*?\\n\\});/.test(dtsContent);\n}","tryCatchPattern":"try {\n  content = await updateConfig(content);\n} catch (e) {\n  if (/Config type not found in config\\.d\\.ts/.test(e.message)) {\n    console.warn('Skipping config section: config.d.ts shape changed.');\n    return content; // keep the previously generated config section\n  }\n  throw e;\n}","preventionTips":["Always run the type-definition build step before update-readme.js in npm scripts.","Keep the emitted Config as a plain object literal type (closing `};` on its own line) rather than an interface or intersection.","Add a CI assertion that the regex in update-readme.js still matches the freshly built config.d.ts."],"tags":["build-script","typescript","regex-parsing","config","developer-tooling","dts-parsing"],"backgroundTag":"regex-extraction-target-missing","analyzedSha":"16cf228d7b02c07f800ec3423f471ec2a42d22a9","analyzedAt":"2026-08-27T04:02:08.206Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}