← All guides

How to write a good GitHub issue title, with ten examples

You have the whole bug in your head, the cursor is in the title box, and what comes out is "Export broken".

That line then does more work than it was written for. The title is the part of an issue that travels: the row in the Issues tab, the subject line of every notification, the hovercard on a #412 link, the reference that unfurls when somebody drops the issue into a list, the timeline entry when another thread mentions it. Written inline in a comment, #412 shows only its number, so the title is what appears the moment anybody stops to look. The body appears only once somebody has decided to open it.

The short version

  • Name the thing affected, using a noun from the product.
  • Say what it does, not that it is broken.
  • Add the condition, if it fits in about three words.
  • Put the recognisable words first.
  • Write it last, after the body.

If you do only two of these, do the first two. A noun and a verb are the pair almost every weak title is missing, and supplying them takes seconds.

Write the title last

A title is a summary, and summaries come after the thing they summarise. You clicked New issue with a feeling. By the time the body is filled in you have facts instead. Read the body back, then write the title from what is on the page rather than from what you meant when you started.

We keep saying this for a concrete reason. A bare title with nothing under it is the shape of the worst issues we see, common enough that our own code stores the title on its own when the body is empty, because sometimes it is all there is. One of them was "Read me" with a link under it and nothing else. The title was not really the fault there. It was just the only thing present.

Name the thing, then say what it does

Subject and verb. "CSV export" plus "stops at 1,000 rows". A title built out of a mood rather than a noun gives a reader nothing to match against what they know of the code.

Nothing to match on

Broken since yesterday

A noun and a verb

CSV export stops at 1,000 rows

The verb should be what you saw, not that something failed. "Fails" covers an error message, a silent no-op, a partial result and a wrong result that looked fine. A good title is the one line version of your reproduction steps: the thing, the action, the outcome. The rest of the bug report supplies how to get there.

Add the condition, if it fits in three words

"on ranges over 1,000 rows". "on Safari only". "since 2.4.0". "first login after signup". The condition is what lets somebody scanning five export issues tell yours apart from the other four. If it needs a sentence, it belongs in the body.

That is a claim about reading a list, not about duplicates. Whether two issues are the same issue is a question about causes, and two titles that read alike are weak evidence either way. If the condition is "sometimes", give a rate instead: "about one login in three" says more than "intermittent", and the rest of what an intermittent bug needs goes in the body.

What to put first

Openers that spend the opening on nothing: "Bug:", "Issue with", "Question about", "Help needed", a component prefix the label already carries, and a ticket number that is already in the URL. Read these as a list, which is how they will be read.

Five rows you have to open
  • Bug: export
  • [Reports] Issue with exporting
  • Question about export limits
  • Help needed with CSV
  • #4521 export problem
Five rows you can skim
  • CSV export stops at 1,000 rows
  • CSV export drops the header row on Safari
  • Export limit of 1,000 rows: intended, or a bug?
  • CSV export times out on ranges over 90 days
  • Export button does nothing on an empty range

The second list can be read in one pass. The first has to be opened, one row at a time, to find out which is which.

The list you will scan in a year

Somebody will come back to this issue months from now: a colleague, or you. The second case is the argument for writing the issue for the person who picks it up in four months, applied to a single field.

What that person does is search, then scan. GitHub searches the title, the body and the comments by default, so a word you left out of the title is not lost: it will still be found in the body. That cuts both ways. A search for "export" in a busy repository returns everything anybody has ever said about exports, which is why maintainers narrow it with in:title. That is the search your title has to survive, and the rows it returns are the list your title has to be recognisable in.

What does not belong in a title

Urgency. "URGENT", "ASAP", three exclamation marks. A title cannot establish priority, triage will set it anyway, and inflating it costs you the next report.

Your diagnosis. "Cache invalidation broken" is a guess promoted to a heading, and a guess in the heading tends to route the issue toward the component you guessed.

An @name, ALL CAPS, or an emoji. A title is plain text, not markdown, so an @name in it is not a link and notifies nobody: put it in the body if you need somebody. All three cost you characters that could have carried the condition.

A question mark, when the body is a bug report. Phrase it as a question and it gets read, and triaged, as a question.

Ten titles

These are the shapes that recur, not quotations from anyone's tracker. Nine of them want rewriting and the tenth does not. Each rewrite stays under about twelve words.

Filed

It doesn't work

Rewritten

CSV export stops at 1,000 rows

"It doesn't work" is at least eight different outcomes. The rewrite commits to one of them.

Filed

URGENT!!! Please fix ASAP

Rewritten

Checkout fails at the payment step for all users, since 2.4.0

Filed

Login bug

Rewritten

Login rejects a correct password on the first attempt after signup

Filed

Question

Rewritten

Does the 1,000 row export limit apply per report or per account?

Filed

Same as #412

Rewritten

Export stops at 1,000 rows on the Reports page, as in #412

Keep the cross-reference, add the content. A title that is only a pointer stops working the day #412 is closed as something else.

Filed

Feature request

Rewritten

No way to export more than 1,000 rows

Filed

When I try to export the report after setting a date range, the file that downloads is missing most of the rows, and I am not sure whether that is the range or the size

Rewritten

CSV export drops rows on ranges over 1,000

Filed

NullPointerException: Cannot invoke Report.getRows() because report is null

Rewritten

Export throws on an empty range, with a null report

The trace is evidence, so keep it. It goes in the first line of the body, where it can be read and searched without crowding out the thing that broke.

Filed

Increase the export timeout to 60 seconds

Rewritten

Export times out on ranges over 90 days

The first names a fix, and if the fix is wrong the title is wrong with it. The second names the fault, which stays true whatever the fix turns out to be.

Leave it alone

Dark mode toggle resets on reload

Notice what the rewrites have in common. Each one is the sentence somebody writes after reading the whole issue, which means the better title already exists: it is just written by the wrong person, too late, in a comment. WhatProblem writes that sentence too. Its first reply restates the problem in a sentence or two, in the reporter's own terms, so the reporter can correct it, and that restatement is the raw material for a title if you want to use it. It will not retitle anything itself. Editing the title stays a human job.

Requests, questions, and renaming somebody else's

A feature request title names the problem, not the feature. "No way to export more than 1,000 rows" invites a decision about the problem. "Add pagination to export" asks for a verdict on one solution, and if the team would have solved it another way, the title has already argued them out of it.

A question title contains the question, with its subject in it. "Question about limits" is a notification nobody can act on. "Does the 1,000 row export limit apply per report or per account?" can be answered by whoever reads it first.

Renaming somebody else's issue is part of triage work, though it takes more than the Triage role to do it: the author can edit a title, and so can anyone with write access or above. Triage permission covers labels, assignees, milestones and closing, but not the title. GitHub records the rename in the issue's timeline. Do three things when you rename. Leave the reporter's original words untouched in the body, so nobody loses the phrasing they will search for. Say in a comment that you renamed it and why. And keep the rename to what they told you, because a silent rewrite of somebody's issue into your own terms reads as being overruled, and the next thing they file will be shorter.

WhatProblem does this in the issue thread

It reads new GitHub issues and asks what is missing, a minute or two after they are opened, before anyone on your team has to.

Install from GitHub Marketplace