From 0d6fe3c52fcb6576fd2016383b6251ba9b153088 Mon Sep 17 00:00:00 2001 From: Ilya Kiselev Date: Sat, 21 Mar 2026 00:26:12 +0300 Subject: [PATCH] fix(engine): make toToml return empty string on error, add mustToToml Previously, toToml returned err.Error() on marshal failure, which was inconsistent with toYaml and toJson (both return "" on error). This commit: - Changes toToml to return "" on error, aligning it with toYaml/toJson - Adds mustToToml that panics on error, consistent with mustToYaml/mustToJson - Registers mustToToml in the template function map - Adds tests covering the error-swallowing behavior and mustToToml Fixes #31430 Signed-off-by: Ilya Kiselev --- pkg/engine/funcs.go | 19 ++++++++++++++++++- pkg/engine/funcs_test.go | 12 ++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pkg/engine/funcs.go b/pkg/engine/funcs.go index ba842a51a..0615284e9 100644 --- a/pkg/engine/funcs.go +++ b/pkg/engine/funcs.go @@ -50,6 +50,7 @@ func funcMap() template.FuncMap { // Add some extra functionality extra := template.FuncMap{ "toToml": toTOML, + "mustToToml": mustToTOML, "fromToml": fromTOML, "toYaml": toYAML, "mustToYaml": mustToYAML, @@ -157,7 +158,23 @@ func toTOML(v any) string { e := toml.NewEncoder(b) err := e.Encode(v) if err != nil { - return err.Error() + // Swallow errors inside of a template. + return "" + } + return b.String() +} + +// mustToTOML takes an interface, marshals it to toml, and returns a string. +// It will panic if there is an error. +// +// This is designed to be called from a template when need to ensure that the +// output TOML is valid. +func mustToTOML(v any) string { + b := bytes.NewBuffer(nil) + e := toml.NewEncoder(b) + err := e.Encode(v) + if err != nil { + panic(err) } return b.String() } diff --git a/pkg/engine/funcs_test.go b/pkg/engine/funcs_test.go index 48202454e..2d61dde8a 100644 --- a/pkg/engine/funcs_test.go +++ b/pkg/engine/funcs_test.go @@ -86,6 +86,11 @@ keyInElement1 = "valueInElement1"`, tpl: `{{ toToml . }}`, expect: "[mast]\n sail = \"white\"\n", vars: map[string]map[string]string{"mast": {"sail": "white"}}, + }, { + // toToml should return empty string on error, not the error message + tpl: `{{ toToml . }}`, + expect: "", // should return empty string and swallow error + vars: map[int]string{1: "one"}, }, { tpl: `{{ fromYaml . }}`, expect: "map[Error:error unmarshaling JSON: while decoding JSON: json: cannot unmarshal array into Go value of type map[string]interface {}]", @@ -159,6 +164,13 @@ keyInElement1 = "valueInElement1"`, tpl: `{{ toJson . }}`, expect: "", // should return empty string and swallow error vars: loopMap, + }, { + tpl: `{{ mustToToml . }}`, + vars: map[int]string{1: "one"}, // non-string key is invalid in TOML + }, { + tpl: `{{ mustToToml . }}`, + expect: "foo = \"bar\"\n", // should succeed and return TOML string + vars: map[string]string{"foo": "bar"}, }, }