Skip to content

fix(changelog): Prevent IndexError for empty paragraphs#1446

Open
soyamigo wants to merge 2 commits into
python-semantic-release:masterfrom
soyamigo:master
Open

fix(changelog): Prevent IndexError for empty paragraphs#1446
soyamigo wants to merge 2 commits into
python-semantic-release:masterfrom
soyamigo:master

Conversation

@soyamigo

@soyamigo soyamigo commented Jun 12, 2026

Copy link
Copy Markdown

Purpose

Fixes an IndexError crash in autofit_text_width when a commit body contains whitespace-only lines. When PSR parses such a commit and splits the body into paragraphs, a whitespace-only line produces an empty words list after filtering. The subsequent line = words[0] then raises IndexError: list index out of range, aborting changelog generation entirely.

This is the full stacktrace:

IndexError: list index out of range

Traceback (most recent call last):
  File "~/.venv/lib/python3.11/site-packages/semantic_release/__main__.py", line 16, in main
    cli_main(args=sys.argv[1:])
  File "~/.venv/lib/python3.11/site-packages/click/core.py", line 1161, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/click/core.py", line 1082, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/click/core.py", line 1697, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/click/core.py", line 1443, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/click/decorators.py", line 45, in new_func
    return f(get_current_context().obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/semantic_release/cli/commands/version.py", line 647, in version
    write_changelog_files(
  File "~/.venv/lib/python3.11/site-packages/semantic_release/cli/changelog_writer.py", line 214, in write_changelog_files
    write_default_changelog(
  File "~/.venv/lib/python3.11/site-packages/semantic_release/cli/changelog_writer.py", line 154, in write_default_changelog
    changelog_text = render_default_changelog_file(
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/semantic_release/cli/changelog_writer.py", line 82, in render_default_changelog_file
    changelog_content = template.render().rstrip()
                        ^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/jinja2/environment.py", line 1295, in render
    self.environment.handle_exception()
  File "~/.venv/lib/python3.11/site-packages/jinja2/environment.py", line 942, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "~/.venv/lib/python3.11/site-packages/semantic_release/data/templates/conventional/md/CHANGELOG.md.j2", line 18, in top-level template code
    %}{%    include ".components/changelog_update.md.j2"
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/semantic_release/data/templates/conventional/md/.components/changelog_update.md.j2", line 57, in top-level template code
    }}{%-       include "versioned_changes.md.j2"
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/semantic_release/data/templates/conventional/md/.components/versioned_changes.md.j2", line 19, in top-level template code
    %}{%  include "changes.md.j2"
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/semantic_release/data/templates/conventional/md/.components/changes.md.j2", line 51, in top-level template code
    %}{%      set description = description | autofit_text_width(max_line_width, hanging_indent)
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.venv/lib/python3.11/site-packages/semantic_release/changelog/context.py", line 173, in autofit_text_width
    line = words[0]
           ~~~~~^^^

::ERROR:: list index out of range

Rationale

The words list is already constructed with a filter(None, ...) call to strip empty strings, so an empty result after that filter means the paragraph itself was blank or whitespace-only. The correct behavior is to skip such paragraphs entirely, which is consistent with what the surrounding split("\n\n") loop is trying to do — process meaningful paragraph blocks. A simple if not words: continue guard before accessing words[0] is the minimal, safe fix.

How did you test?

Reproduced the crash locally by running semantic-release version against a repository containing commits with whitespace-only lines in their bodies (e.g. a line containing only spaces or tabs). Confirmed the IndexError occurred before the fix and that changelog generation completed successfully after applying it.

Edge cases considered:

  • Paragraph that is entirely whitespace; skipped cleanly
  • Paragraph with leading/trailing blank lines but valid content; unaffected, strip() handles it upstream
  • Normal single and multi-paragraph commit bodies; behavior unchanged

How to Verify

  1. Create a git repo with at least one conventional commit whose body contains a line of only whitespace (e.g. )
  2. Run semantic-release version - observe the IndexError: list index out of range crash
  3. Apply this patch
  4. Run semantic-release version again to make sure changelog generates successfully

PR Completion Checklist

  • Reviewed & followed the Contributor Guidelines

  • Changes Implemented & Validation pipeline succeeds

  • Commits follow the Conventional Commits standard
    and are separated into the proper commit type and scope (recommended order: test, build, feat/fix, docs)

  • Appropriate Unit tests added/updated

  • Appropriate End-to-End tests added/updated

  • Appropriate Documentation added/updated and syntax validated for sphinx build (see Contributor Guidelines)

@soyamigo

Copy link
Copy Markdown
Author

FWIW, ran the CI(manual) workflow in my fork: https://github.com/soyamigo/python-semantic-release/actions/runs/27431762140

Seems to be okay.

Automatically generated by python-semantic-release
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant