{"record":{"id":"7c72ea9b36ec5b64","repo":"angular/components","slug":"could-not-read-file-for-path-htmlfilepath","errorCode":null,"errorMessage":"Could not read file for path: ${htmlFilePath}","messagePattern":"Could not read file for path: (.+?)","errorType":"exception","errorClass":"SchematicsException","httpStatus":null,"severity":"error","filePath":"src/cdk/schematics/utils/html-manipulation.ts","lineNumber":18,"sourceCode":"/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {SchematicsException, Tree} from '@angular-devkit/schematics';\nimport {Element, getChildElementIndentation} from './parse5-element';\nimport {parse as parseHtml} from 'parse5';\n\n/** Appends the given element HTML fragment to the `<head>` element of the specified HTML file. */\nexport function appendHtmlElementToHead(host: Tree, htmlFilePath: string, elementHtml: string) {\n  const htmlFileBuffer = host.read(htmlFilePath);\n\n  if (!htmlFileBuffer) {\n    throw new SchematicsException(`Could not read file for path: ${htmlFilePath}`);\n  }\n\n  const htmlContent = htmlFileBuffer.toString();\n\n  if (htmlContent.includes(elementHtml)) {\n    return;\n  }\n\n  const headTag = getHtmlHeadTagElement(htmlContent);\n\n  if (!headTag) {\n    throw Error(`Could not find '<head>' element in HTML file: ${htmlFileBuffer}`);\n  }\n\n  // We always have access to the source code location here because the `getHeadTagElement`\n  // function explicitly has the `sourceCodeLocationInfo` option enabled.\n  const endTagOffset = headTag.sourceCodeLocation!.endTag!.startOffset;\n  const indentationOffset = getChildElementIndentation(headTag);","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/schematics/utils/html-manipulation.ts#L1-L36","documentation":"appendHtmlElementToHead in src/cdk/schematics/utils/html-manipulation.ts reads the target HTML file (normally the app's index.html) from the schematic virtual host Tree before appending an element to its <head>. If host.read(htmlFilePath) returns null the file does not exist at that path in the virtual file system, and a SchematicsException is thrown. The library cannot modify a file it cannot read, so it fails fast.","triggerScenarios":"Running a schematic that injects into index.html (e.g. addFontsToIndex for Material typography/fonts) when the resolved index path does not exist in the Tree; a project whose architect build options lack an index entry the schematic can resolve; an unusual custom index file name/location not registered in angular.json.","commonSituations":"Custom index filename (e.g. src/index.dev.html) not declared in angular.json; index.html deleted or moved during refactoring; monorepo layouts where sourceRoot does not point at the app root; running the schematic on a partially generated project.","solutions":["Verify the project's build architect options in angular.json contain a correct \"index\" path and that the file exists on disk.","Restore or recreate index.html at the configured path (a standard Angular app has src/index.html).","If you use a custom index name, register it under projects.<name>.architect.build.options.index so schematics can resolve it.","Re-run `ng build` or `ng serve` once to confirm the workspace resolves the index file, then retry the schematic."],"exampleFix":"// before (angular.json)\n\"options\": { \"main\": \"src/main.ts\" }\n// after (angular.json)\n\"options\": { \"main\": \"src/main.ts\", \"index\": \"src/index.html\" }","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nconst index = JSON.parse(fs.readFileSync('angular.json', 'utf8'))\n  .projects[name]?.architect?.build?.options?.index ?? 'src/index.html';\nif (!existsSync(index)) throw new Error(`index.html missing at ${index}`);","typeGuard":"function hasIndexOption(opts: Record<string, unknown> | undefined): opts is Record<string, unknown> & { index: string } {\n  return !!opts && typeof opts.index === 'string';\n}","tryCatchPattern":"try {\n  await runSchematic('add-fonts', { project: name });\n} catch (e) {\n  if (String(e.message).startsWith('Could not read file for path')) {\n    console.error('index.html not found; verify the project build \"index\" option.');\n  } else throw e;\n}","preventionTips":["Keep index.html at src/index.html and registered in angular.json build options.","Do not delete or rename index.html without updating the \"index\" config key.","Run schematics from the workspace root so relative paths resolve."],"tags":["angular","schematics","index-html","file-not-found"],"backgroundTag":"file-not-found","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}