Skip to content

fix(links): prevent nil-map panic in build_links on Hugo >= 0.162#3329

Open
Vidminas wants to merge 1 commit into
HugoBlox:mainfrom
Vidminas:fix/build-links-nil-map
Open

fix(links): prevent nil-map panic in build_links on Hugo >= 0.162#3329
Vidminas wants to merge 1 commit into
HugoBlox:mainfrom
Vidminas:fix/build-links-nil-map

Conversation

@Vidminas

Copy link
Copy Markdown

Hugo 0.162 changed dict so that an empty (dict) returns a non-writable nil map. build_links pre-seeded its dedup set with $seen.Set "set" (dict) and then wrote to it via $seen.SetInMap "set" .... Because the Scratch key already existed, SetInMap skipped its internal make() and assigned straight into the nil map, panicking with "assignment to entry in nil map" while rendering any page that emits a link.

Drop the pre-seed; SetInMap creates a writable map on first use, which is correct on every Hugo version.

πŸš€ What type of change is this?

  • πŸ› Bug fix (A non-breaking change that fixes an issue)
  • ✨ New feature (A non-breaking change that adds functionality)
  • πŸ’… Style change (A change that only affects formatting, visuals, or styling)
  • πŸ“š Documentation update (Changes to documentation only)
  • 🧹 Refactor or chore (A code change that neither fixes a bug nor adds a feature)
  • πŸ’₯ Breaking change (A fix or feature that would cause existing functionality to not work as expected)

🎯 What is the purpose of this change?

Fixes a total build failure on Hugo β‰₯ 0.162.0. Any site that renders a page with links
(portfolio items, publications, anything using page_links / the citation view / the cite
shortcode) aborts the build with:

error calling SetInMap: assignment to entry in nil map
… _partials/functions/build_links.html:55

Full CI log:

Details
 echo "Hugo Cache Dir: $(hugo config | grep cachedir)"
  hugo --minify --baseURL "[https://vidminas.github.io/"](https://vidminas.github.io/%22)
  shell: /usr/bin/bash -e {0}
  env:
    NODE_VERSION: 22
    PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
    HUGO_VERSION: 0.162.0
    GITHUB_PAGES: true
    HUGO_ENVIRONMENT: production
    HUGO_BLOX_LICENSE: 
hugo: collected modules in 11711 ms
Hugo Cache Dir: cachedir = '/home/runner/.cache/hugo_cache'
Start building sites … 
hugo v0.162.0-076dfe13d0f789e3d9586b192f8f7f3329c26990+extended linux/amd64 BuildDate=2026-05-26T13:53:44Z VendorInfo=gohugoio
ERROR error building site: render: [en v1.0.0 guest] failed to render pages: render of "/home/runner/work/vidminas.github.io/vidminas.github.io/content/_index.md" failed:
"/home/runner/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/!hugo!blox/kit/modules/blox@v0.0.0-20260527025321-61f41d3667f1/layouts/landing/list.html:2:5": execute of template failed:
template: landing/list.html:2:5: executing "main" at <partial "landing_page.html" .>: error calling partial:
"/home/runner/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/!hugo!blox/kit/modules/blox@v0.0.0-20260527025321-61f41d3667f1/layouts/_partials/landing_page.html:11:7": execute of template failed:
template: _partials/landing_page.html:11:7: executing "_partials/landing_page.html" at <partial "functions/parse_block_v3" (dict "page" $ "block" $block)>: error calling partial:
"/home/runner/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/!hugo!blox/kit/modules/blox@v0.0.0-20260527025321-61f41d3667f1/layouts/_partials/functions/parse_block_v3.html:365:7": execute of template failed:
template: _partials/functions/parse_block_v3.html:365:7: executing "_partials/functions/parse_block_v3.html" at <partial $block_path $widget_args>: error calling partial:
"/home/runner/work/vidminas.github.io/vidminas.github.io/layouts/_partials/hbx/blocks/portfolio/block.html:417:15": execute of template failed:
template: _partials/hbx/blocks/portfolio/block.html:417:15: executing "_partials/hbx/blocks/portfolio/block.html" at <partial "page_links" (dict "page" $item "is_list" 1)>: error calling partial:
"/home/runner/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/!hugo!blox/kit/modules/blox@v0.0.0-20260527025321-61f41d3667f1/layouts/_partials/page_links.html:5:13": execute of template failed: template:
_partials/page_links.html:5:13: executing "_partials/page_links.html" at <partial "functions/build_links" (dict "page" $page "is_list" $is_list)>: error calling partial:
"/home/runner/.cache/hugo_cache/modules/filecache/modules/pkg/mod/github.com/!hugo!blox/kit/modules/blox@v0.0.0-20260527025321-61f41d3667f1/layouts/_partials/functions/build_links.html:55:14": execute of template failed: template:
_partials/functions/build_links.html:55:14: executing "_partials/functions/build_links.html" at <$seen.SetInMap>: error calling SetInMap: assignment to entry in nil map

Root cause. Hugo 0.162 changed collections.Dictionary so that an empty (dict) now
returns a non-writable nil map (its own comment: "this cannot be written to … If we do,
that's a bug"
). build_links.html pre-seeded its dedup set with {{ $seen.Set "set" (dict) }}
and then wrote to it via {{ $seen.SetInMap "set" … }}. Because the Scratch key set already
existed, Scratch.SetInMap skipped its internal make(map[string]any) and assigned straight
into the nil map β†’ panic. Hugo ≀ 0.161 was unaffected (there an empty dict was writable).

Fix (one line). Drop the pre-seed. SetInMap auto-creates a writable map on first use when
the key is absent, so the dedup set still works β€” correct on every Hugo version.

Reproduced the panic and verified the fix by building the academic-cv starter on Hugo
0.162.0
(fails on main, 93 pages / exit 0 with this change) and re-checked on 0.161.1.

Note (out of scope, not changed here): the dedup is effectively a no-op regardless β€” the read
{{ $seen.Get (printf "set.%s" $keyF) }} is a flat Scratch lookup of the literal key
"set.<key>", but the entries live one level down inside the set map, so the guard never
matches. Harmless unless a page has genuinely duplicate links; happy to fix in a follow-up
(flat-key the Scratch) if desired.


πŸ“Έ Screenshots or Screencast (if applicable)

n/a β€” build-time fix (no visual change).


ℹ️ Documentation Check

  • No, this change does not require a documentation update.
  • Yes, I have updated the documentation accordingly (or will in a follow-up PR).

πŸ“œ Contributor Agreement

Thank you for your contribution!

Hugo 0.162 changed `dict` so that an empty `(dict)` returns a non-writable
nil map. build_links pre-seeded its dedup set with `$seen.Set "set" (dict)`
and then wrote to it via `$seen.SetInMap "set" ...`. Because the Scratch key
already existed, SetInMap skipped its internal make() and assigned straight
into the nil map, panicking with "assignment to entry in nil map" while
rendering any page that emits a link.

Drop the pre-seed; SetInMap creates a writable map on first use, which is
correct on every Hugo version.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Vidminas Vidminas requested a review from gcushen as a code owner July 10, 2026 07:34
@netlify

netlify Bot commented Jul 10, 2026

Copy link
Copy Markdown

βœ… Deploy Preview for academic-demo canceled.

Name Link
πŸ”¨ Latest commit 5258532
πŸ” Latest deploy log https://app.netlify.com/projects/academic-demo/deploys/6a50a0a09a43b00008bde38f

@github-actions

Copy link
Copy Markdown
Contributor

Wow, your first PR! Welcome to the community! πŸŽ‰

Thank you for this contribution to open source and open research. It makes a huge impact for the thousands of innovators building with Hugo Blox.

If you're wondering about next steps, please read our Contributor Guide for coding standards, how to run the project locally, and how to get help.

We hope this is just the start of your journey with us. Let's build the future together! Join us on Discord to connect with the team and community.

Awesome work, we'll take a look soon! ✨

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant