Skip to content

Fixed panic and bugs in Exists()/GetValue()#206

Merged
inhere merged 2 commits intogookit:masterfrom
killabytenow:bugfix-exists
Mar 21, 2026
Merged

Fixed panic and bugs in Exists()/GetValue()#206
inhere merged 2 commits intogookit:masterfrom
killabytenow:bugfix-exists

Conversation

@killabytenow
Copy link
Copy Markdown
Contributor

@killabytenow killabytenow commented Mar 20, 2026

I found several bugs in Exists() and GetValue(). The following test results in panics instead of finding the entries or returning expected results:

package main

import (
	"fmt"

	"github.com/gookit/config/v2"
	"github.com/gookit/config/v2/yaml"
)

type test struct {
	expected bool
	path     string
}

func run_test(t test) {
	var at_func string
	defer func() {
		if recover() != nil {
			fmt.Printf("[PANIC!] %s (at %s)\n", t.path, at_func)
		}
	}()

	result := "FAILED"
	at_func = "Exists"
	exists := config.Exists(t.path)
	at_func = "GetValue"
	v, ok := config.GetValue(t.path)
	if exists == t.expected && ok == t.expected {
		result = "  OK  "
	}
	fmt.Printf("[%s] %s: Exists() = %v ; GetValue() = (%v, %v)\n", result, t.path, exists, v, ok)

}

func main() {
	// config.ParseEnv: will parse env var in string value. eg: shell: ${SHELL}
	config.WithOptions(config.ParseEnv)

	// add driver for support yaml content
	config.AddDriver(yaml.Driver)

	yamlConfig := `
app:
  name: MyApp
  version: 1.0.0
lol:
  - test:
      bu: 1
      ba: ugly
      foo:
        - 1
        - 2
        - 3
  - another:
      - "pingu"
      - "pangu"
    gajo: nil
`

	err := config.LoadStrings(config.Yaml, yamlConfig)
	if err != nil {
		panic(err)
	}

	for _, t := range []test{
		{true, "lol"},
		{true, "lol.0"},
		{true, "lol.0.test.ba"},
		{true, "lol.0.test.foo"},
		{true, "lol.0.test.foo.0"},
		{true, "lol.0.test.foo.1"},
		{true, "lol.1.another.0"},
		{true, "lol.1.another.1"},
		{false, "lol.1.another.2"},
		{true, "lol.1.gajo"},
		{false, "lol.2"},
		{false, "lol.2.wat"},
	} {
		run_test(t)
	}
}

This small contribution/patch should fix this unexpected behavior.

@killabytenow
Copy link
Copy Markdown
Contributor Author

This is the result when running with current version (v2.2.7):

$ go run test.go 
[  OK  ] lol: Exists() = true ; GetValue() = ([map[test:map[ba:ugly bu:1 foo:[1 2 3]]] map[another:[pingu pangu] gajo:nil]], true)
[  OK  ] lol.0: Exists() = true ; GetValue() = (map[test:map[ba:ugly bu:1 foo:[1 2 3]]], true)
[FAILED] lol.0.test.ba: Exists() = false ; GetValue() = (ugly, true)
[FAILED] lol.0.test.foo: Exists() = false ; GetValue() = ([1 2 3], true)
[FAILED] lol.0.test.foo.0: Exists() = false ; GetValue() = (1, true)
[FAILED] lol.0.test.foo.1: Exists() = false ; GetValue() = (2, true)
[FAILED] lol.1.another.0: Exists() = false ; GetValue() = (pingu, true)
[FAILED] lol.1.another.1: Exists() = false ; GetValue() = (pangu, true)
[PANIC!] lol.1.another.2 (at GetValue)
[FAILED] lol.1.gajo: Exists() = false ; GetValue() = (nil, true)
[PANIC!] lol.2 (at GetValue)
[PANIC!] lol.2.wat (at GetValue)

And this with this patch applied:

$ go run test.go 
[  OK  ] lol: Exists() = true ; GetValue() = ([map[test:map[ba:ugly bu:1 foo:[1 2 3]]] map[another:[pingu pangu] gajo:nil]], true)
[  OK  ] lol.0: Exists() = true ; GetValue() = (map[test:map[ba:ugly bu:1 foo:[1 2 3]]], true)
[  OK  ] lol.0.test.ba: Exists() = true ; GetValue() = (ugly, true)
[  OK  ] lol.0.test.foo: Exists() = true ; GetValue() = ([1 2 3], true)
[  OK  ] lol.0.test.foo.0: Exists() = true ; GetValue() = (1, true)
[  OK  ] lol.0.test.foo.1: Exists() = true ; GetValue() = (2, true)
[  OK  ] lol.1.another.0: Exists() = true ; GetValue() = (pingu, true)
[  OK  ] lol.1.another.1: Exists() = true ; GetValue() = (pangu, true)
[  OK  ] lol.1.another.2: Exists() = false ; GetValue() = (<nil>, false)
[  OK  ] lol.1.gajo: Exists() = true ; GetValue() = (nil, true)
[  OK  ] lol.2: Exists() = false ; GetValue() = (<nil>, false)
[  OK  ] lol.2.wat: Exists() = false ; GetValue() = (<nil>, false)

@inhere inhere merged commit d3d8407 into gookit:master Mar 21, 2026
9 checks passed
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.

3 participants