GPLv2 vs GPLv3 Compatibility: What You Must Know Before Releasing

May 21, 2026 7 min read 37 views
Two mismatched puzzle pieces in blue and green tones against a minimal geometric background, representing a software license incompatibility

You're days from shipping, and someone on the team notices a dependency is GPLv2-only. Your project already pulls in a GPLv3 library. Now you have a legal incompatibility that could block the release entirely β€” not because anyone did anything malicious, but because two of the most widely-used open source licenses simply do not mix.

This is a surprisingly common trap. The GPL family is everywhere in open source, but the version differences have real consequences that are easy to miss until they bite you.

What You'll Learn

  • Why GPLv2 and GPLv3 are incompatible with each other and what that means in practice
  • How to read license headers and spot the critical "or later" clause
  • How to audit your dependency tree for GPL conflicts before they block a release
  • What your practical options are when you discover a conflict
  • Where LGPL and AGPL fit into this picture

Prerequisites

No specific tooling required, though the examples reference pip and npm package ecosystems. A basic understanding of what open source licenses are β€” you use code that other people wrote under certain conditions β€” is enough to follow along.

Why GPL Versions Are Not Interchangeable

The GNU General Public License is a copyleft license, meaning any software you distribute that incorporates GPL-licensed code must itself be distributed under a compatible GPL license. That's the core mechanism that keeps open source open.

GPLv2 was published in 1991. GPLv3 came out in 2006 and added new provisions β€” most importantly, explicit patent grants and anti-tivoization clauses (restrictions on using software in hardware that prevents users from running modified versions). These additions are valuable to many contributors, but they are legally distinct terms.

Because GPLv3 adds requirements that GPLv2 does not, a work licensed solely under GPLv2 cannot be combined with a work licensed under GPLv3. You cannot satisfy both licenses at the same time when distributing the combined work. The Free Software Foundation confirmed this explicitly: the two licenses are incompatible with each other.

The "Or Later" Clause Changes Everything

This is where most developers get confused. There are actually three distinct situations you can encounter when reading a GPL notice:

  • GPLv2 only β€” The copyright holder chose version 2 specifically, and that is the only license under which you can use the work. Linux kernel code is the most prominent example.
  • GPLv2 or later β€” The copyright holder allows use under GPLv2, GPLv3, or any future GPL version. This is written as "GPL version 2 or (at your option) any later version." Code under this notice is compatible with GPLv3.
  • GPLv3 only β€” Version 3 specifically, no earlier versions.

When a project says it is "GPL-licensed" without specifying a version, check the actual license file or SPDX identifier. Many older projects default to GPLv2-only. Assuming "GPL means GPL" across versions is exactly how you end up with a conflict.

Reading the SPDX Identifiers

Modern packages often use SPDX identifiers in their package.json, pyproject.toml, or COPYING file. Here's what you'll see:

SPDX IdentifierMeaningCompatible with GPLv3?
GPL-2.0-onlyGPLv2, no later versionsNo
GPL-2.0-or-laterGPLv2 or any later versionYes
GPL-3.0-onlyGPLv3, no earlier versionsYes (same version)
GPL-3.0-or-laterGPLv3 or any later versionYes

If you see GPL-2.0-only anywhere in your dependency graph alongside a GPL-3.0-only dependency, you have an incompatibility that needs resolving before you ship.

How to Audit Your Dependency Tree

Manual inspection does not scale. Run a license audit tool early and run it often β€” not just before a release deadline.

Python Projects

The pip-licenses package generates a report of all installed packages and their licenses:

pip install pip-licenses
pip-licenses --format=markdown --with-license-file

Look for any entry that reports GPL-2.0 without the "or later" qualifier. Cross-reference those against any GPLv3 dependencies in the same list.

Node.js Projects

The license-checker package does the same for npm dependency trees:

npm install -g license-checker
license-checker --summary --excludePrivatePackages

You can also filter for specific licenses:

license-checker --onlyAllow "MIT;ISC;Apache-2.0;BSD-2-Clause;BSD-3-Clause"

If that command exits with an error, you have a dependency that does not match your allow-list β€” worth investigating immediately.

For Any Language: REUSE and SPDX Bills of Materials

The REUSE specification (from the FSFE) and SPDX Software Bill of Materials (SBOM) formats are becoming standard in compliance workflows. Many CI pipelines now generate an SBOM automatically. If yours does not, it is worth adding one. Tools like syft can generate an SPDX or CycloneDX SBOM from most build artifacts:

syft packages dir:. -o spdx-json > sbom.json

Review the output for any GPL-2.0-only entries when your project has GPLv3 requirements elsewhere.

Where LGPL and AGPL Fit In

While you're auditing, you'll likely encounter two other members of the GPL family:

LGPL (Lesser GPL) β€” Available in v2.1 and v3. LGPL allows linking from non-GPL code without triggering the copyleft requirement, as long as you allow users to relink with a modified version of the LGPL library. LGPLv2.1 and LGPLv3 have the same version-compatibility dynamics as their GPL counterparts. LGPLv3 explicitly states it is a set of additional permissions on top of GPLv3, which means LGPLv3 code is compatible with GPLv3 code.

AGPL (Affero GPL) β€” Version 3 of AGPL is designed to be compatible with GPLv3. The key addition is that running AGPL software as a network service counts as distribution, so the source-sharing requirement applies. If you include an AGPLv3 dependency, your entire combined work may need to comply with AGPLv3 terms.

Your Options When You Find a Conflict

Discovering a GPLv2-only dependency in a GPLv3 project doesn't mean you're stuck. You have several paths:

1. Ask the Copyright Holder to Relicense

If the GPLv2-only dependency is a small, actively maintained project, reach out to the maintainers. Many chose GPLv2 by default rather than by strong conviction, and they may be willing to add "or later" to their license notice. Get this in writing (a public commit or issue comment works).

2. Find an Alternative Dependency

Often there's a functionally equivalent library under a permissive license (MIT, Apache-2.0) or under a compatible GPL version. Replacing the dependency entirely eliminates the conflict and usually improves your dependency hygiene anyway.

3. Isolate the Dependency via a Subprocess or API Boundary

If the GPLv2-only component runs as a separate process and communicates over a well-defined interface (a socket, a REST API, a command-line call), the copyleft requirement may not propagate to your main codebase. This is a gray area that depends on the nature of the interaction and jurisdiction, so get a legal opinion if your project carries significant commercial risk.

4. Relicense Your Own Project

If you control all the copyright in your project and the GPLv2-only dependency is genuinely the best tool for the job, you could choose to release your project under GPLv2-or-later instead of GPLv3-only. This moves your project down to the common denominator. You lose GPLv3's patent and anti-tivoization protections, so weigh that tradeoff deliberately.

5. Do Not Ship Until It's Resolved

This sounds harsh, but shipping a release that violates GPL terms is a legal risk, not just a licensing preference. GPL enforcement actions have resulted in injunctions and legal costs. The fix is usually faster than the fallout.

Common Pitfalls

Transitive dependencies are invisible until they're not. A library you depend on may pull in a GPLv2-only package two or three levels deep. Your direct dependency list looking clean means nothing. Always audit the full tree.

"GPL" in documentation is ambiguous. If a project's README says "Licensed under the GPL" without a version number, check the actual LICENSE or COPYING file. Some projects have outdated docs that don't match their actual license file.

Dual-licensed code is not a conflict. Many projects are explicitly dual-licensed β€” for example, under both GPLv2 and MIT, or under GPLv2-or-later. In these cases, you choose the license that works for your situation. Document your choice explicitly in your own license notices.

Static vs. dynamic linking matters less than you think. The GPL's application to linked code is not solely determined by whether you link statically or dynamically. The FSF's position is that both can create a combined work subject to GPL terms. Don't rely on dynamic linking as a compliance shortcut without legal review.

Your CI passing doesn't mean your licenses are clean. License compliance is not a unit test. Add a license audit step to your pipeline explicitly so it fails visibly when a new dependency brings in a problem.

Adding a License Audit to Your CI Pipeline

Here is a minimal GitHub Actions example that fails the build if any dependency uses a non-approved license:

name: License Check
on: [push, pull_request]
jobs:
  license-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npx license-checker --onlyAllow "MIT;ISC;Apache-2.0;BSD-2-Clause;BSD-3-Clause;GPL-2.0-or-later;GPL-3.0-only;GPL-3.0-or-later"

Adjust the allow-list to match your project's licensing policy. Running this on every pull request catches problems at the point they're introduced, not the day before a release.

Wrapping Up

GPL version conflicts are easy to overlook and genuinely disruptive when you catch them late. Here are the concrete actions to take now:

  1. Run a full license audit today. Use pip-licenses, license-checker, or a similar tool on your current dependency tree. Don't wait for a release crunch.
  2. Add a license audit step to your CI pipeline. Make it a failing check, not an optional report. Catch new problems at the PR stage.
  3. Learn to read SPDX identifiers. The difference between GPL-2.0-only and GPL-2.0-or-later is not cosmetic β€” it determines whether your combination is legal to distribute.
  4. Have a resolution plan before you need one. Know whether you'd replace, isolate, or relicense an incompatible dependency. Decisions made under deadline pressure tend to be worse.
  5. Document your licensing decisions in your repo. A LICENSES/ directory or a REUSE configuration makes it clear to future contributors and auditors exactly what you chose and why.

πŸ“€ Share this article

Sign in to save

Comments (0)

No comments yet. Be the first!

Leave a Comment

Sign in to comment with your profile.

πŸ“¬ Weekly Newsletter

Stay ahead of the curve

Get the best programming tutorials, data analytics tips, and tool reviews delivered to your inbox every week.

No spam. Unsubscribe anytime.