Short answer
LSP says a subtype must be usable anywhere its supertype is expected without breaking the program's correctness — overrides shouldn't strengthen preconditions or weaken postconditions.
Explanation
The textbook violation is Square extends Rectangle: setting width independently of height breaks invariants callers of Rectangle rely on. Another common one is an override that throws UnsupportedOperationException (e.g., an immutable List's add), which technically satisfies the type but violates the behavioral contract callers expect.
Common mistakes
- Quoting the rectangle/square example without explaining which client expectation breaks.
- Treating LSP as a rule about method signatures only rather than behaviour.