Most repos already have a GitHub team behind them — the developers who actually work on that codebase. If that team is not named in CODEOWNERS, the repo does not know it exists at review time. Pull requests go out with nobody attached, the right people find out by accident, and an approval can come from someone who has never worked on the code.
A CODEOWNERS file maps path patterns to owners. When a pull request touches a matching path, GitHub requests a review from those owners automatically.
# .github/CODEOWNERS* @jane-dev @sam-dev
❌ Bad example - Named individuals go stale, and duplicate the team membership you already maintain
# .github/CODEOWNERS# The repo's developer team owns everything by default* @SSWConsulting/cleanarchitecture# A narrower owner for a sensitive area/.github/ @SSWConsulting/devops
✅ Good example - The team owns the repo, so membership stays correct as people join and leave
The people who own the code are asked for the review, every time, without anyone remembering to add them. Choosing reviewers by hand means the busy or the nearby get picked, and the person who knows that area finds out after the merge.
GitHub only accepts a code owner who has write access to the repo. An owner without it is ignored — silently, which is its own trap, so check for it (see below). That makes the team the boundary: approval authority follows the team, and the team follows the repo.
Turn on Require review from Code Owners in your branch protection, and an approval from outside the team no longer satisfies the requirement. Somebody with broad access across the whole organization cannot rubber stamp a change in a repo they have nothing to do with, because their approval does not count towards it.
This restricts whose approval counts, not who can click the button. Someone with a bypass permission can still merge around branch protection, so keep the list of people who hold it short — see Do you limit admin access? and Do you know when to override branch protection?.
Figure: Code owners restrict whose approval counts
Without it, CODEOWNERS only suggests reviewers. It enforces nothing.
mainCODEOWNERS fails quietly. The two failures worth knowing:
@org/team on its own line is read as a path with no owners, so it matches nothing and requests nobody. Write * @org/team insteadNeither failure produces a warning in a pull request, so verify it directly:
gh api repos/OWNER/REPO/codeowners/errors
GitHub shows the same errors when you open the CODEOWNERS file in the browser. Check it after any change to the file, and after anyone leaves the team.