fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body - #20

Merged
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length
Aug 13, 2026
Merged

fix: stop submitting the whole ever-growing CHANGELOG.md as the Modrinth version body#20
KP2048 merged 1 commit into
1.21.xfrom
worktree-fix-modrinth-changelog-length

Conversation

@KP2048

Copy link
Copy Markdown
Member

Summary

`publishModrinth` was failing with:

EndpointException(error=invalid_input, description=Error while validating input: Field version_body failed validation with error: length)

`publisher { changelog = file("CHANGELOG.md") }` submits that file's entire content as the version body on every publish. `generate_release_notes.py`'s `update_changelog()` only ever prepends - CHANGELOG.md accumulates every release's notes forever, and Modrinth's `version_body` has a length limit (~65536 chars) that a large enough cumulative history eventually exceeds. CurseForge tolerated the same payload; Modrinth didn't.

A second, related bug made this worse in practice: the pre-publish flow (`generateChangelog`) passes `--new-tag` as the intended, not-yet-real version. Retrying a failed local publish re-runs it with the exact same range/version and got a fresh duplicate section prepended every single time instead of regenerating the existing one in place - which is exactly how a local CHANGELOG.md ends up with the same version's section repeated many times over.

Fixes

  • `generate_release_notes.py`: `update_changelog()` now replaces the existing top section instead of prepending a duplicate when it's for the same version already at the top of the file (safe/correct for the real post-tag flow too, where each version is genuinely only ever generated once).
  • New `--latest-path`: writes just this release's own rendered body (no accumulated history), independent of whatever's already in CHANGELOG.md.
  • `build.gradle.kts`: `generateChangelog` now also writes `build/latest-changelog.md`; `publisher.changelog` points there instead of `CHANGELOG.md`.

Verification

A single generated release covering this repo's entire history (66 entries, worst case - no previous tag) renders to ~11KB, comfortably under Modrinth's limit. Re-running the script twice for the same version now leaves exactly one section in CHANGELOG.md instead of two.

🤖 Generated with Claude Code

…nth version body
publishModrinth started failing with:
EndpointException(error=invalid_input, description=Error while
validating input: Field version_body failed validation with error: length)
publisher { changelog = file("CHANGELOG.md") } submits that file's entire
content as the version body on every publish. generate_release_notes.py's
update_changelog() only ever prepends - CHANGELOG.md accumulates every
release's notes forever, and Modrinth's version_body has a length limit
(~65536 chars) that a large enough cumulative history eventually exceeds
(CurseForge tolerated it; Modrinth didn't).
A second, related bug made this worse in practice: the pre-publish flow
(generateChangelog) passes --new-tag as the *intended*, not-yet-real
version - retrying a failed local publish re-runs it with the exact same
range/version and got a fresh duplicate section prepended every time
instead of regenerating the existing one in place.
Fixes:
- generate_release_notes.py: update_changelog() now replaces the existing
top section instead of prepending a duplicate when it's for the same
version already at the top of the file (safe/correct for the real
post-tag flow too, where each version is genuinely only ever generated
once).
- New --latest-path: writes just this release's own rendered body (no
accumulated history), completely independent of whatever's already in
CHANGELOG.md.
- build.gradle.kts: generateChangelog now also writes
build/latest-changelog.md; publisher.changelog points there instead of
CHANGELOG.md.
Verified: a single generated release covering this repo's entire history
(66 entries, worst case - no previous tag) renders to ~11KB, comfortably
under Modrinth's limit. Re-running the script twice for the same version
now leaves exactly one section in CHANGELOG.md instead of two.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CopilotAI lite review requested due to automatic review settings August 13, 2026 05:45

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KP2048
KP2048 merged commit c4f6d46 into 1.21.xAug 13, 2026
5 of 6 checks passed
@KP2048
KP2048 deleted the worktree-fix-modrinth-changelog-length branch August 13, 2026 05:46
Sign up for freeto 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.

2 participants

@KP2048