Skip to content

IndexOutOfRangeException in InjectSnippetsIntoFile when snippet insertion is at end of file #314

@gavinbarron

Description

@gavinbarron

Bug

InjectSnippetsIntoFile crashes with System.ArgumentOutOfRangeException when the snippet insertion point is at or near the end of a documentation file.

Stack trace

System.AggregateException: One or more errors occurred.
  (Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index'))
 ---> System.ArgumentOutOfRangeException: Index was out of range.
   at System.Collections.Generic.List1.get_Item(Int32 index)
   at System.Linq.Enumerable.ElementAt[TSource](IEnumerable1 source, Int32 index)
   at ApiDoctor.ConsoleApp.Program.InjectSnippetsIntoFile(MethodDefinition method, String codeSnippets)
     in Program.cs:line 2513
   at ApiDoctor.ConsoleApp.Program.GenerateSnippetsAsync(GenerateSnippetsOptions options, ...)
     in Program.cs:line 2002

Root cause

After Splice removes the old snippet tab section, the collection shrinks. The code then unconditionally accesses updatedFileContents.ElementAt(insertionLine + 1) without checking bounds. When the insertion point is at or near the end of the file (no trailing content after the code block), insertionLine + 1 exceeds the collection size.

Affected code

// Program.cs, in the InsertSnippets block:
updatedFileContents = updatedFileContents.Splice(insertionLine, snippetsTabSectionEndLine - insertionLine);
if (!string.IsNullOrWhiteSpace(codeSnippets))
{
    // BUG: no bounds check before ElementAt
    if (!string.IsNullOrWhiteSpace(updatedFileContents.ElementAt(insertionLine + 1)))
        codeSnippets = $"{codeSnippets}\r\n";
    updatedFileContents = FileSplicer(updatedFileContents.ToArray(), insertionLine, codeSnippets);
}

Fix

Add a bounds check before accessing ElementAt:

if (insertionLine + 1 < updatedFileContents.Count()
    && !string.IsNullOrWhiteSpace(updatedFileContents.ElementAt(insertionLine + 1)))

This skips appending the trailing newline when the insertion point is at the end of the file, which is the correct behavior — there's no subsequent content to separate from.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions