{"record":{"id":"fa4bff5ca9d99f99","repo":"angular/angular-cli","slug":"tried-to-insert-toinsert-as-first-occurence-wit","errorCode":null,"errorMessage":"tried to insert ${toInsert} as first occurence with no fallback position","messagePattern":"tried to insert (.+?) as first occurence with no fallback position","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/schematics/angular/utility/ast-utils.ts","lineNumber":253,"sourceCode":" */\nexport function insertAfterLastOccurrence(\n  nodes: ts.Node[] | ts.NodeArray<ts.Node>,\n  toInsert: string,\n  file: string,\n  fallbackPos: number,\n  syntaxKind?: ts.SyntaxKind,\n): Change {\n  let lastItem: ts.Node | undefined;\n  for (const node of nodes) {\n    if (!lastItem || lastItem.getStart() < node.getStart()) {\n      lastItem = node;\n    }\n  }\n  if (syntaxKind && lastItem) {\n    lastItem = findNodes(lastItem, syntaxKind).sort(nodesByPosition).pop();\n  }\n  if (!lastItem && fallbackPos == undefined) {\n    throw new Error(`tried to insert ${toInsert} as first occurence with no fallback position`);\n  }\n  const lastItemPosition: number = lastItem ? lastItem.getEnd() : fallbackPos;\n\n  return new InsertChange(file, lastItemPosition, toInsert);\n}\n\nfunction _angularImportsFromNode(node: ts.ImportDeclaration): { [name: string]: string } {\n  const ms = node.moduleSpecifier;\n  let modulePath: string;\n  switch (ms.kind) {\n    case ts.SyntaxKind.StringLiteral:\n      modulePath = (ms as ts.StringLiteral).text;\n      break;\n    default:\n      return {};\n  }\n\n  if (!modulePath.startsWith('@angular/')) {","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/schematics/angular/utility/ast-utils.ts#L235-L271","documentation":"insertAfterLastOccurrence (a shared AST mutation helper in ast-utils) computes the insertion position from the last occurrence of the given syntax kind among the found nodes. If no nodes were found and no explicit fallbackPos was provided, it cannot determine where to insert and throws this Error.","triggerScenarios":"Calling helpers like insertImport or addRouteDeclarationToModule against a source file whose AST contains no node of the expected syntax kind (e.g. importing into an empty/nonexistent imports section) without passing a fallbackPos, or passing an incorrect syntaxKind for the file's content shape.","commonSituations":"Custom schematics built on ast-utils running against files that don't match the expected structure (empty files, files with only comments, non-TS content); upgrading Angular where file templates changed; passing wrong syntax kind when writing custom codemods.","solutions":["Pass an explicit `fallbackPos` (e.g. 0 or end-of-file offset) when calling insertAfterLastOccurrence on files that may lack the expected node.","Verify the target file contains the expected syntax (e.g. existing imports) before mutating; create/normalize the file first.","Use ts.createSourceFile to inspect the file and adjust the syntaxKind argument to one actually present.","Regenerate or fix the malformed source file that the codemod is targeting."],"exampleFix":"// before\nconst change = insertAfterLastOccurrence(nodes, toInsert, file, undefined, ts.SyntaxKind.CommaToken);\n// after\nconst change = insertAfterLastOccurrence(nodes, toInsert, file, 0, ts.SyntaxKind.CommaToken);","handlingStrategy":"try-catch","validationCode":"const imports = source.statements.filter(ts.isImportDeclaration);\nif (imports.length === 0) {\n  console.warn('No import declarations found; pass an explicit fallbackPos to insertAfterLastOccurrence.');\n}","typeGuard":"function hasNodes(nodes: ts.Node[]): nodes is [ts.Node, ...ts.Node[]] {\n  return nodes.length > 0;\n}","tryCatchPattern":"try {\n  const change = insertAfterLastOccurrence(nodes, toInsert, file, fallbackPos ?? 0, syntaxKind);\n} catch (e) {\n  if (String(e?.message).includes('no fallback position')) {\n    // file lacks the expected node; insert at a known position instead\n  }\n}","preventionTips":["Always provide a fallbackPos when writing custom codemods with ast-utils.","Inspect the target file's AST before mutating; guard for empty or comment-only files.","Pin ast-utils usage to the Angular version matching the files being transformed.","Test codemods against empty and minimal file fixtures."],"tags":["typescript","ast","schematics","codemod"],"backgroundTag":"ast-insert-no-fallback-position","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}