config: Skip taxonomy entries with empty keys or values

When non-taxonomy keys (e.g. disableKinds = []) are placed after
[taxonomies] in TOML, they become part of the taxonomies table.
An empty-valued entry creates a phantom taxonomy with an empty
pluralTreeKey, causing .Ancestors to loop indefinitely.

Fixes #14550

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bjørn Erik Pedersen
2026-02-23 11:03:38 +01:00
parent cc338a9d48
commit 65b4287c68
3 changed files with 35 additions and 1 deletions
+1
View File
@@ -8,6 +8,7 @@
* Avoid global state at (almost) all cost.
* This is a project with a long history; assume that a similiar problem has been solved before, look hard for helper functions before creating new ones.
* In tests, use `qt` matchers (e.g. `b.Assert(err, qt.ErrorMatches, ...)`) instead of raw `if`/`t.Fatal` checks.
* In tests, always use the latest Hugo specification, e.g. for layouts, it's `layouts/page.html` and not `layouts/_default/single.html`, `layouts/list.html` and not `layouts/_default/list.html`
* Brevity is good. This applies to code, comments and commit messages. Don't write a novel.
* Use `./check.sh ./somepackage/...` when iterating.
* Use `./check.sh` when you're done.
+8 -1
View File
@@ -335,7 +335,14 @@ var allDecoderSetups = map[string]decodeWeight{
key: "taxonomies",
decode: func(d decodeWeight, p decodeConfig) error {
if p.p.IsSet(d.key) {
p.c.Taxonomies = hmaps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
m := hmaps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
// Remove invalid entries (e.g. non-taxonomy keys placed inside [taxonomies] in TOML).
for k, v := range m {
if k == "" || v == "" {
delete(m, k)
}
}
p.c.Taxonomies = m
}
return nil
},
+26
View File
@@ -334,3 +334,29 @@ title: "Page 2 nn"
b.AssertFileExists("public/nn/p1/index.html", false)
b.AssertFileExists("public/nn/p2/index.html", false)
}
// Issue #14550
// disableKinds = [] after [taxonomies] is inside the taxonomies TOML table,
// creating a phantom taxonomy that causes .Ancestors to hang.
func TestDisableKindsEmptySliceAncestors(t *testing.T) {
files := `
-- hugo.toml --
baseURL = "http://example.com/"
title = "Bug repro"
[taxonomies]
tag = "tags"
disableKinds = []
-- content/posts/hello.md --
---
title: Hello
tags: [demo]
---
Hello.
-- layouts/page.html --
Ancestors: {{ len .Ancestors }}|{{ range .Ancestors }}{{ .Kind }}|{{ end }}
-- layouts/list.html --
{{ .Title }}
`
b := Test(t, files)
b.AssertFileContent("public/posts/hello/index.html", "Ancestors: 2|section|home|")
}