Azure DevOps release notes missing work items: 5 causes and fixes
Michael Thomsen
·7 min read
Short answer: Azure DevOps only associates a work item with a pipeline run when it is linked to a commit or pull request within the changes since the last successful run, and that range is capped at 250 changes. Work items outside that window, linked from another repository, or merged without a merge commit never appear. Fix the linking rules first, then decide whether a build is the right source at all.
The question recurs in the GitHub discussions of the free Generate Release Notes task and on Microsoft Q&A. In June 2022 one team on Azure DevOps Server counted 186 work items linked to commits in a first-time run and got 78 in the generated file. A month later Microsoft told them the number of changes linked to a run is capped at 250, and in 2024 confirmed the limit will stay.
How Azure DevOps decides which work items belong to a run
Before blaming the task, understand what the platform hands it. According to Microsoft's documentation on pipeline and work tracking integration:
- For the first run of a pipeline on a branch, Azure DevOps collects work items linked to the branch, its commits and its pull requests.
- For every later run, it only looks at the commits between the current commit and the commit of the last successful run on the same branch.
- Links only count if the user who linked them has Edit work items in this node permission on the work item's area path.
- Work items in GitHub repositories only link when the pull request description contains the
AB#123syntax. - The list of changes considered per run is limited to 250.
Release notes tasks, including the Bravo Notes build task with the "Associated work items" source, can only render what this list contains.
The five causes, in the order to check them
1. The work item is linked to a commit outside the comparison window
If a feature took six weeks and the final merge happened in a pipeline run that also contained 300 other commits, the oldest 50 are dropped. The symptom is that the missing items are always the older ones.
Check: call the Build Work Items REST endpoint for the run (/_apis/build/builds/{buildId}/workitems?$top=5000) and compare the count with what you expected. If the API returns fewer items than your commit history shows, you have hit the cap.
2. The pipeline was rerun without new commits
A rerun of the same pipeline, or a deployment pipeline that only downloads artifacts, has no commits of its own. The maintainer of the Generate Release Notes task answers this at least once a month: "My task can only compare a run against previous runs of the same build definition." Generate the notes in the build that produced the artifact, not in the release that deploys it, or use a source that does not depend on commits.
3. Pull requests were completed without a merge commit
Squash merges and rebase merges do not leave the merge commit the comparison APIs look for. The PR exists, its linked work items exist, but the run never sees them. Either switch the branch policy to a standard merge, or link work items to the commits themselves with #123 in the commit message.
4. The job authorization scope is limited
With Limit job authorization scope to current project enabled, work items in other projects of the same organization come back as empty arrays. The same applies to Limit job authorization scope to referenced Azure DevOps repositories when the Wiki or another repository is involved. Both settings live under Project settings, Pipelines, Settings.
5. The template is the wrong format for the task
Several threads with "my notes are empty" end with a template written for a different task version. Handlebars syntax looks the same at a glance, but each tool exposes different objects. If your output shows literal {{...}} placeholders, the template never ran against the data at all.
When a build is the wrong source for release notes
A pipeline run answers "which commits are in this build?". Release notes answer "what changed for the user since the last release?". The two overlap but differ. Teams that release every sprint, hotfix out of band, or ship from several repositories find the commit-based list wrong in both directions. It misses items, and it includes work that was merged but sits behind a feature flag.
The alternative is to make the work items themselves the source of truth and pick them with a query:
- A query for State = Closed and Closed Date within the last 14 days gives you a sprint's release notes regardless of which builds carried the code.
- A query on a Release or Fixed in custom field gives you release notes for a named version.
- A query on Tags contains customer-visible gives you the subset you actually want to publish.
Queries are visible, testable and editable by the product owner, which is rarely true for commit ranges.
Doing this with Bravo Notes
Bravo Notes is a paid Azure DevOps extension (30-day free trial) that renders release notes from work items through a template. Its build task offers several work item sources, so you can pick the one that matches how your team releases:
| Source | Best for |
|---|---|
| Associated work items | Teams with strict commit linking and one repository per product |
| Associated work items since a starting commit | Hotfix branches and partial releases |
| Compare with release environment | Everything not yet deployed to Production |
| Query | Sprint-based or version-field-based release notes |
| Iteration: current, previous or next | Sprint reviews and planning documents |
| Pull request | Notes for a single pull request |
| JSON file | Work item IDs produced by your own script |
Whichever source you choose, the same template renders Markdown, HTML or PDF and publishes it to a file, an Azure DevOps Wiki page, a repository or Confluence. The build task documentation lists every option. A minimal template looks like this:
# Release {{ env 'BUILD_BUILDNUMBER' }}
{{#section 'feature'}}
## New features
{{#workItems}}
- **{{ field 'Title' }}** ({{ id }})
{{/workItems}}
{{/section}}
{{#section 'bugfix'}}
## Fixed bugs
{{#workItems}}
- {{ field 'Title' }} ({{ id }})
{{/workItems}}
{{else}}
No bug fixes in this release.
{{/section}}
The feature and bugfix labels are rules you define once, for example "Work Item Type = Bug AND State = Closed", so a reopened bug never sneaks into the fixed list.
Checklist before you trust automated release notes
- Confirm the branch policy requires a linked work item on every pull request.
- Decide whether squash merges are acceptable for your linking strategy.
- Count the changes in a typical run. If it can exceed 250, use a query source.
- Give the build service account Contribute on the Wiki or repository you publish to.
- Generate a draft for one past release and compare it with what you shipped. Fix the rules, not the document.
Frequently asked questions
Does Azure DevOps really limit a pipeline run to 250 changes? Yes. The limit was confirmed by Microsoft in a public discussion in 2022 and again in 2024, and it applies to the changes and work items associated with a run. It is a performance safeguard, not a bug.
Can I generate release notes for a release pipeline instead of a build? Yes, but the work items come from the primary artifact's build and the builds since the previous successful release, so the same linking rules apply. Deployment-only pipelines without a source build have nothing to compare.
What is the easiest way to see which work items Azure DevOps associated with a run? Open the run summary in Azure Pipelines and look at the Work items tab, or call the Build Work Items REST endpoint. Both show exactly what any release notes task receives.
Do I need commits linked to work items if I use a query? No. A query selects work items by their fields, so linking commits becomes optional. Many teams keep linking for traceability but stop depending on it for release notes.
Can the same template be used manually and in the pipeline? In Bravo Notes, yes. The template, labels and parameters are saved once, and both the UI export and the build task use them.
Summarize this article