textwrap.shorten() Drops a Too-Long Word Entirely (tested)
textwrap.shorten() is the common way to truncate a title or summary to fit a fixed width. We measured what it does when the very first word is longer than that width, and it throws the word away completely rather than cutting it down.
1. A word longer than the width disappears, leaving only the placeholder
import textwrap
text = "Supercalifragilisticexpialidocious is a word"
print(repr(textwrap.shorten(text, width=20)))
print(repr(textwrap.shorten(text, width=38)))
'[...]'
'[...]'
Measured: at both widths the 34-character first word doesn't fit alongside the ' [...]' placeholder, so shorten() drops the entire word -- not just the overflow -- and returns a string with zero characters of the original text. Nothing in the output hints that there was ever any content there.
2. The word only appears once it fits whole, never partially
for w in (38, 39, 40):
print(w, repr(textwrap.shorten(text, width=w)))
38 '[...]'
39 '[...]'
40 'Supercalifragilisticexpialidocious [...]'
Measured: the word (34 chars) plus the placeholder (' [...]', 6 chars) needs exactly 40 characters. Below that threshold the word is all-or-nothing -- there's no intermediate width where you get even a few characters of it before the placeholder.
3. Why: plain wrap() breaks long words fine; shorten()'s max_lines=1 does not
plain = textwrap.TextWrapper(width=10)
print(plain.wrap(text))
['Supercalif', 'ragilistic', 'expialidoc', 'ious is a', 'word']
Measured: with no max_lines, the same break_long_words=True default behaves as expected, splitting the long word across multiple lines. textwrap.shorten() internally calls TextWrapper(width=width, max_lines=1).fill(...) -- once a placeholder and a one-line limit are both in play, the wrapper's placeholder-fitting logic treats an oversized chunk as unplaceable and omits it wholesale, rather than hyphenating or cutting it down to make room.
4. Fix: check the result, or pre-truncate very long single tokens yourself
result = textwrap.shorten(text, width=20)
if not any(word in result for word in text.split()[:1]):
print("shorten() dropped the leading word entirely")
shorten() dropped the leading word entirely
Measured: there's no built-in flag to make shorten() hyphenate an overlong leading word instead of dropping it. For content that might start with a single long token (URLs, hashtags, compound words, serial numbers), truncate that token manually before calling shorten(), or verify the output still contains part of the original text.
Frequently asked questions
Does textwrap.shorten() partially truncate a word that's too long for the width?
No -- we measured it dropping the entire word and returning only the placeholder, with none of the original word's characters, once the word plus placeholder can't both fit.
Does textwrap.wrap() have the same all-or-nothing problem with long words?
No -- we confirmed plain wrap() (without max_lines) splits long words across multiple lines as expected under its default break_long_words=True behaviour.
Why does shorten() behave differently from wrap() for the same text?
textwrap.shorten() calls TextWrapper with max_lines=1 internally. Once a placeholder and a one-line cap are combined, the wrapper's logic for fitting a line plus placeholder treats an oversized chunk as unplaceable and drops it entirely rather than breaking it.
Can the output of shorten() end up completely unrelated to the input?
Yes in the extreme case -- we measured it returning just '[...]' with zero characters from the original text, which could be misread as an error message rather than a truncated result.
How do I avoid losing all content when shortening text that starts with a long token?
Check whether the result still contains part of the first word, or manually cap very long leading tokens (URLs, hashtags, IDs) before passing the text to textwrap.shorten().
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in textwrap module: ran textwrap.shorten() and the lower-level TextWrapper(max_lines=1) on text starting with a single 34-character word, at a range of width values, and contrasted it with plain textwrap.wrap() (no max_lines) on the identical text. PlainHeaders is our extension; Python's textwrap module is built in.