{"record":{"id":"afc8375a50c66fde","repo":"angular/angular-cli","slug":"preservewhitespaces-was-set-in-tsconfigpath","errorCode":null,"errorMessage":"\"preserveWhitespaces\" was set in \"${tsConfigPath}\". Make sure that this setting is set consistently in both \"tsconfig.server.json\" for your server side and \"tsconfig.app.json\" for your client side. A mismatched value will cause hydration to break.\nFor more information see: https://angular.dev/guide/hydration#preserve-whitespaces-configuration","messagePattern":"\"preserveWhitespaces\" was set in \"(.+?)\"\\. Make sure that this setting is set consistently in both \"tsconfig\\.server\\.json\" for your server side and \"tsconfig\\.app\\.json\" for your client side\\. A mismatched value will cause hydration to break\\.\nFor more information see: https://angular\\.dev/guide/hydration#preserve-whitespaces-configuration","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/angular_devkit/build_angular/src/builders/server/index.ts","lineNumber":261,"sourceCode":"\nasync function checkTsConfigForPreserveWhitespacesSetting(\n  context: BuilderContext,\n  tsConfigPath: string,\n): Promise<void> {\n  // We don't use the `readTsConfig` method on purpose here.\n  // To only catch cases were `preserveWhitespaces` is set directly in the `tsconfig.server.json`,\n  // which in the majority of cases will cause a mistmatch between client and server builds.\n  // Technically we should check if `tsconfig.server.json` and `tsconfig.app.json` values match.\n\n  // But:\n  // 1. It is not guaranteed that `tsconfig.app.json` is used to build the client side of this app.\n  // 2. There is no easy way to access the build build config from the server builder.\n  // 4. This will no longer be an issue with a single compilation model were the same tsconfig is used for both browser and server builds.\n  const content = await readFile(path.join(context.workspaceRoot, tsConfigPath), 'utf-8');\n  const { parse } = await import('jsonc-parser');\n  const tsConfig = parse(content, [], { allowTrailingComma: true });\n  if (tsConfig.angularCompilerOptions?.preserveWhitespaces !== undefined) {\n    context.logger.warn(\n      `\"preserveWhitespaces\" was set in \"${tsConfigPath}\". ` +\n        'Make sure that this setting is set consistently in both \"tsconfig.server.json\" for your server side ' +\n        'and \"tsconfig.app.json\" for your client side. A mismatched value will cause hydration to break.\\n' +\n        'For more information see: https://angular.dev/guide/hydration#preserve-whitespaces-configuration',\n    );\n  }\n}\n\n/**\n * Add `@angular/platform-server` exports.\n * This is needed so that DI tokens can be referenced and set at runtime outside of the bundle.\n */\nfunction getPlatformServerExportsConfig(wco: BrowserWebpackConfigOptions): Partial<Configuration> {\n  // Add `@angular/platform-server` exports.\n  // This is needed so that DI tokens can be referenced and set at runtime outside of the bundle.\n\n  return {\n    module: {","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/build_angular/src/builders/server/index.ts#L243-L279","documentation":"The server builder checks tsconfig.server.json for angularCompilerOptions.preserveWhitespaces. If set, it warns that the value must match tsconfig.app.json, because a mismatch between server and client templates (whitespace handling) breaks Angular hydration.","triggerScenarios":"Building a server target where the parsed tsconfig (jsonc) has `angularCompilerOptions.preserveWhitespaces` defined; the builder warns regardless of the value.","commonSituations":"Projects that set preserveWhitespaces in one tsconfig but not the other; SSR hydration errors (missing/extra text nodes) in production.","solutions":["Remove preserveWhitespaces from tsconfig.server.json (and tsconfig.app.json) so both use the default consistently.","If set intentionally, set the exact same value in both tsconfig.server.json and tsconfig.app.json.","After changing, verify hydration by comparing server-rendered HTML with client-rendered DOM."],"exampleFix":"// tsconfig.server.json\n// before\n\"angularCompilerOptions\": { \"preserveWhitespaces\": false }\n// after: remove the option or mirror it identically in tsconfig.app.json\n\"angularCompilerOptions\": {}","handlingStrategy":"validation","validationCode":"const { readFileSync } = require('fs');\nconst { parse } = require('jsonc-parser');\nconst s = parse(readFileSync('tsconfig.server.json','utf8'), [], { allowTrailingComma: true });\nconst a = parse(readFileSync('tsconfig.app.json','utf8'), [], { allowTrailingComma: true });\nconst sv = s.angularCompilerOptions?.preserveWhitespaces;\nconst av = a.angularCompilerOptions?.preserveWhitespaces;\nif (sv !== undefined && sv !== av) throw new Error('preserveWhitespaces mismatch between server and app tsconfig');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep preserveWhitespaces unset in both tsconfigs unless explicitly required.","Add a config-lint step comparing angularCompilerOptions across tsconfig files.","Test hydration locally whenever compiler options change."],"tags":["angular","ssr","hydration","tsconfig"],"backgroundTag":"hydration-mismatch","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}