Your GitHub repository shows "Other" instead of the correct license badge.
The GitHub API returns "spdx_id": "NOASSERTION" — meaning license detection failed.
This is a common issue for repositories with dual-license or non-standard license file layouts.
# Replace OWNER/REPO with your repository
gh api repos/OWNER/REPO --jq '.license.spdx_id'"MIT","Apache-2.0", etc. — detection works"NOASSERTION"— detection failed (this guide is for you)null— no license file found at all
GitHub uses licensee (a Ruby gem) to detect licenses.
The algorithm:
- Find files matching common license filenames:
LICENSE,LICENSE.md,LICENSE.txt,LICENCE,COPYING,LICENSE-*, etc. - Read the content of the best-matching filename
- Fuzzy-match the content against a corpus of known SPDX license texts
- If similarity ≥ ~90%, identify the license; otherwise return
NOASSERTION
Key behaviors:
licenseeprefers files named exactlyLICENSE(no extension) over others- Files named
LICENSE-*(e.g.,LICENSE-MIT,LICENSE-APACHE-2.0) are recognized as additional license files - The file must contain actual license text, not just a description or links
- The shortest known template (MIT) is ~1000 bytes — a short wrapper file won't match anything
- licensee — What we look at
- licensee — How it works
- SPDX License List
- GitHub docs — Licensing a repository
LICENSE.md ← short markdown with links (NOT actual license text)
LICENSE.Apache-2.0.txt ← full Apache 2.0 text
LICENSE.MIT.txt ← full MIT text
licensee reads LICENSE.md first, finds ~200 bytes of markdown links, can't match it to any known license → NOASSERTION.
License_Apache2.txt ← not recognized as a license filename
mit-license.txt ← not recognized
licensee has a specific list of filename patterns it recognizes. Creative naming causes it to skip the file entirely.
LICENSE ← standard MIT text but with large custom preamble/appendix
If modifications push similarity below ~90%, detection fails.
This is the pattern used by projects like vis-network and many Apache Software Foundation projects:
git mv LICENSE.md LICENSE # or delete it
git mv LICENSE.Apache-2.0.txt LICENSE-APACHE-2.0
git mv LICENSE.MIT.txt LICENSE-MITWhy it works: licensee recognizes LICENSE-APACHE-2.0 as a license file, reads the full Apache 2.0 text, and matches it successfully.
Replace the wrapper with one of the actual license texts:
cp LICENSE-MIT LICENSE # root file = full MIT text
# Keep LICENSE-APACHE-2.0 as the secondary licenseSome projects place both license texts in a single file with a separator:
=== MIT License ===
[full MIT text]
=== Apache License 2.0 ===
[full Apache 2.0 text]
This works but licensee will typically only detect the first/primary license.
cp LICENSE.Apache-2.0.txt COPYINGlicensee also recognizes COPYING as a license filename (common in GPL projects).
License detection updates are not instant. GitHub re-runs licensee periodically or when files change on the default branch.
# Check after merge (may take a few minutes)
gh api repos/OWNER/REPO --jq '.license.spdx_id'
# Expected: "Apache-2.0", "MIT", or whichever license is in the primary fileYou can also test locally before pushing:
# Install licensee (requires Ruby)
gem install licensee
# Run against your local repo
licensee detect .File renaming only affects GitHub's UI detection. Package manager metadata is independent:
- npm:
"license": "(Apache-2.0 OR MIT)"inpackage.json(docs) - Cargo:
license = "Apache-2.0 OR MIT"inCargo.toml(docs) - PyPI:
license = "Apache-2.0 OR MIT"inpyproject.toml
These use SPDX expressions directly and are unaffected by file naming.