{"record":{"id":"04de496b5c8621be","repo":"angular/angular-cli","slug":"invalid-file-replacement-json-stringify-filerep","errorCode":null,"errorMessage":"Invalid file replacement: ${JSON.stringify(fileReplacement)}","messagePattern":"Invalid file replacement: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/build_angular/src/utils/normalize-file-replacements.ts","lineNumber":62,"sourceCode":"  }\n\n  return normalizedReplacement;\n}\n\nfunction normalizeFileReplacement(\n  fileReplacement: FileReplacement,\n  root: string,\n): NormalizedFileReplacement {\n  let replacePath: string;\n  let withPath: string;\n  if (fileReplacement.src && fileReplacement.replaceWith) {\n    replacePath = fileReplacement.src;\n    withPath = fileReplacement.replaceWith;\n  } else if (fileReplacement.replace && fileReplacement.with) {\n    replacePath = fileReplacement.replace;\n    withPath = fileReplacement.with;\n  } else {\n    throw new Error(`Invalid file replacement: ${JSON.stringify(fileReplacement)}`);\n  }\n\n  return {\n    replace: path.join(root, replacePath),\n    with: path.join(root, withPath),\n  };\n}\n","sourceCodeStart":44,"sourceCodeEnd":70,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/build_angular/src/utils/normalize-file-replacements.ts#L44-L70","documentation":"normalizeFileReplacement accepts each fileReplacements entry in one of two shapes: the current { replace, with } or the legacy { src, replaceWith }. If an entry matches neither shape, this error is thrown with the JSON of the offending object. It is a schema validation guarding against malformed or mixed-format replacement entries.","triggerScenarios":"A fileReplacements array in angular.json containing an entry like { \"src\": \"a.ts\", \"with\": \"b.ts\" } or { \"replace\": \"a.ts\", \"replaceWith\": \"b.ts\" } (mixing old/new keys), or an entry missing one of the two required keys, or a plain string / null / wrong-typed element.","commonSituations":"Upgrading from old Angular CLI versions where fileReplacements used src/replaceWith and doing a partial rename in the config, IDE snippets with wrong keys, or programmatically generated configs (schematics/build scripts) emitting mixed fields.","solutions":["Rewrite the entry to the current format: { \"replace\": \"<original file>\", \"with\": \"<replacement file>\" }.","Remove legacy keys src/replaceWith or migrate them to replace/with consistently.","Validate the JSON structure of fileReplacements in angular.json — every element must have exactly the pair replace+with (all strings)."],"exampleFix":"// before (angular.json, mixed legacy keys)\n\"fileReplacements\": [{ \"src\": \"src/environments/environment.ts\", \"with\": \"src/environments/environment.prod.ts\" }]\n// after\n\"fileReplacements\": [{ \"replace\": \"src/environments/environment.ts\", \"with\": \"src/environments/environment.prod.ts\" }]","handlingStrategy":"type-guard","validationCode":"// Reject malformed entries before the build\nfunction validFileReplacement(fr) {\n  return fr != null && typeof fr === 'object' &&\n    ((typeof fr.replace === 'string' && typeof fr.with === 'string') ||\n     (typeof fr.src === 'string' && typeof fr.replaceWith === 'string'));\n}\nschema.fileReplacements?.forEach(fr => { if (!validFileReplacement(fr)) throw new Error(`Bad fileReplacements entry: ${JSON.stringify(fr)}`); });","typeGuard":"function isFileReplacement(v) {\n  return v != null && typeof v === 'object' &&\n    ((typeof (v as any).replace === 'string' && typeof (v as any).with === 'string') ||\n     (typeof (v as any).src === 'string' && typeof (v as any).replaceWith === 'string'));\n}","tryCatchPattern":"try {\n  await runBuild(schema);\n} catch (err) {\n  if (/^Invalid file replacement:/.test(err?.message ?? '')) {\n    const bad = err.message.slice('Invalid file replacement: '.length);\n    console.error(`Malformed fileReplacements entry: ${bad} — use { replace, with }.`);\n    process.exitCode = 1;\n  } else throw err;\n}","preventionTips":["After migrating from legacy src/replaceWith, remove old keys entirely rather than mixing formats.","Type angular.json fileReplacements with a discriminated schema so editors flag wrong keys.","Validate config with the workspace schema (ng build validates) before custom tooling consumes it."],"tags":["angular-cli","file-replacements","schema-validation","configuration"],"backgroundTag":"schema-validation-failed","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}