Guide · updated 4 October 2026
GitHub issue template for bug reports: a form you can copy
A blank GitHub issue gets you a one-line bug report with no steps and no build number. A template asks for the missing parts before the issue is saved. Here is how they work, and three files you can copy.
How GitHub issue templates work
Templates live in one folder on the repository's default branch: .github/ISSUE_TEMPLATE/. Each file in it becomes a choice on the New issue page. When someone picks one, the issue starts from that template instead of an empty box.
There are two kinds of template:
- Markdown templates (
.md). A block of text that pre-fills the issue body. Front matter at the top sets the name, title and labels. People can delete any of it. - Issue forms (
.yml). A real form with text boxes, dropdowns and required fields. GitHub will not create the issue until the required fields are filled. The answers are written into the issue as headed sections.
A third file, config.yml, sits in the same folder. It controls the chooser itself: blank_issues_enabled decides whether people can still open an issue with no template, and contact_links adds links that send questions and security reports somewhere else.
The folder ends up like this:
.github/ISSUE_TEMPLATE/bug_report.yml— the form.github/ISSUE_TEMPLATE/config.yml— the chooser settings
The bug report issue form
Use a form for bug reports. Required fields are the only reliable way to get steps and a build number. This one asks for what happened, steps, the expected result, platform, version, browser or device, severity, and screenshots. Save it as .github/ISSUE_TEMPLATE/bug_report.yml.
name: Bug report
description: Something in the app does not work as it should.
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for reporting this. One bug per report, please.
Search the open issues first in case it is already known.
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Describe what you saw, in your own words.
placeholder: The Pay button spins forever and the order is never placed.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: Numbered steps somebody else can follow from the start.
placeholder: |
1. Sign in as a customer with a saved card
2. Add any item to the cart
3. Tap Checkout, then Pay
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected result
description: What should have happened instead?
placeholder: The order is placed and a receipt screen opens.
validations:
required: true
- type: dropdown
id: platform
attributes:
label: Platform
description: Where did it happen? Pick every one you saw it on.
multiple: true
options:
- Web
- iOS
- Android
- Desktop
validations:
required: true
- type: input
id: version
attributes:
label: App version or build
description: Found in Settings > About, or the TestFlight / Play build number.
placeholder: 2.4.1 (build 318)
validations:
required: true
- type: input
id: device
attributes:
label: Browser or device
placeholder: Chrome 129 on macOS, or iPhone 15 on iOS 18.1
validations:
required: false
- type: dropdown
id: severity
attributes:
label: Severity
options:
- Blocker - cannot continue at all
- Major - a main feature is broken
- Minor - works, but wrongly
- Cosmetic - looks wrong only
validations:
required: false
- type: textarea
id: evidence
attributes:
label: Screenshots or recording
description: Drag images or a short screen recording into this box.
validations:
required: false
A few things about the syntax, so your own edits stay valid:
- Every item under
body:has atype:markdown,textarea,input,dropdownorcheckboxes. idmust be unique, and only letters, numbers,-and_. Markdown blocks do not need one.validations.required: truemakes a field mandatory. Markdown blocks cannot be required.multiple: trueon a dropdown lets people pick more than one option.- Labels in
labels:are only applied if they exist in the repository.bugexists by default. - A broken form does not show in the chooser. Open the file on GitHub after you push: it shows a preview, or the error.
The Markdown alternative
If you would rather keep it loose, a Markdown template does the same job with no validation. Save it as .github/ISSUE_TEMPLATE/bug_report.md. Use one or the other for bugs, not both, or the chooser shows two bug reports.
--- name: Bug report about: Something in the app does not work as it should. title: "[Bug]: " labels: bug assignees: "" --- ## What happened? ## Steps to reproduce 1. 2. 3. ## Expected result ## Platform Web / iOS / Android / Desktop ## App version or build ## Browser or device ## Severity Blocker / Major / Minor / Cosmetic ## Screenshots or recording
The chooser: config.yml
Turning off blank issues means every bug arrives through the template. Contact links keep questions out of the bug list. Replace the URLs with your own.
blank_issues_enabled: false
contact_links:
- name: Questions and help
url: https://github.com/your-org/your-repo/discussions
about: Ask how something works. Bugs go in a bug report.
- name: Security problem
url: https://example.com/security
about: Please report security issues privately, not in a public issue.
Tips that make the template work
- Keep required fields few. Require what you cannot fix without: what happened, steps, expected result, platform and build. Make the rest optional. A form with ten required boxes gets abandoned or filled with “n/a”.
- Always ask for the build or version. “It's broken” on last week's build may already be fixed. Without a build number nobody can tell.
- Write placeholders as examples. A placeholder that shows a good answer gets better answers than a description of what to write.
- One bug per issue. Say so at the top of the form. Two bugs in one issue means one gets closed and the other is forgotten.
- Link the fix. Put
Fixes #123in the pull request description. When it merges into the default branch, GitHub closes issue #123 and links the two.
For what makes a good report in general, whatever tool it is written in, see the bug report template guide.
Where a template stops
A template helps people write a good report. It does nothing after that. When the pull request merges, GitHub closes the issue, and that is the end of it. Nobody tells the tester the fix has landed. Nobody checks the bug is actually gone on the build they were testing. A closed issue means the code changed, not that the bug is fixed.
This matters most when testers are not developers and do not live in GitHub.
How QA Runbook closes the loop
In QA Runbook, testers raise the bug against the check they were running, and it gets a short code like QA-13. Connect the app to its GitHub repository and the rest follows:
- You can choose to file every new issue in the connected repository automatically. It opens as a GitHub issue with its code in the title and a link back. Or send issues one at a time.
- A pull request that says
Fixes QA-13, orFixes #8for the GitHub issue, marks it fixed in QA Runbook when it merges. The code also works in the pull request title or branch name. - The tester who raised it is told to check it again. The check shows
reteston the platforms it affects, instead of quietly going back to passing.
Developers keep working in GitHub. Testers keep working in the runbook. Both see the same state. Setup takes a few minutes: see Mark issues fixed from GitHub.