Repository: googleapis/genai-toolbox (Go)

Issue:
Specifying array parameter without items fielld throws nil pointer error
#### Environment details

  - Programming language: Terminal
  - OS: OSX
  - Language runtime version: 
  - Package version: 0.1.0

#### Steps to reproduce

  1. Use a tools.yaml where the entry has an array parameter without the "items" details
  2. Instead of a helpful error message you get a hard Unmarshal Exception

```yaml
tools:
  companies_in_articles:
    kind: neo4j-cypher
    source: companies-graph
    statement: |
      MATCH (a:Article)-[:MENTIONS]->(c)
      WHERE a.id in $ids AND not exists { (c)<-[:HAS_SUBSIDARY]-() }
      RETURN c.id as id, c.name as name, c.summary as summary
    description: Companies (id, name, summary) mentioned in articles by list of article ids
    parameters:
      - name: ids
        type: array
        description: List of article ids to find companies mentioned in
```

```shell
$ ./toolbox --tools_file tools.yaml
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x105083e08]

goroutine 1 [running]:
github.com/googleapis/genai-toolbox/internal/util.(*DelayedUnmarshaler).Unmarshal(...)
        /workspace/internal/util/util.go:39
github.com/googleapis/genai-toolbox/internal/tools.parseParamFromDelayedUnmarshaler(0x14000260638)
        /workspace/internal/tools/parameters.go:182 +0x38
github.com/googleapis/genai-toolbox/internal/tools.(*ArrayParameter).UnmarshalYAML(0x14000274420, 0x14000276cc0)
        /workspace/internal/tools/parameters.go:532 +0xb0
github.com/goccy/go-yaml.(*Decoder).decodeByUnmarshaler(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x105f10be0?, 0x14000274420?, 0x104a9e7cc?}, {0x1061b1c60, 0x14000248d00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:905 +0x490
github.com/goccy/go-yaml.(*Decoder).decodeValue(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x105f10be0?, 0x14000274420?, 0x10493a6c0?}, {0x1061b1c60, 0x14000248d00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:980 +0x1394
github.com/goccy/go-yaml.(*Decoder).decodeByUnmarshaler.func2({0x105f61fa0?, 0x14000274420?})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:910 +0x118
github.com/googleapis/genai-toolbox/internal/util.(*DelayedUnmarshaler).Unmarshal(...)
        /workspace/internal/util/util.go:39
github.com/googleapis/genai-toolbox/internal/tools.parseParamFromDelayedUnmarshaler(0x14000124058)
        /workspace/internal/tools/parameters.go:219 +0x258
github.com/googleapis/genai-toolbox/internal/tools.(*Parameters).UnmarshalYAML(0x14000278318, 0x14000276c30)
        /workspace/internal/tools/parameters.go:169 +0xdc
github.com/goccy/go-yaml.(*Decoder).decodeByUnmarshaler(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x105ddb100?, 0x14000278318?, 0x11?}, {0x1061b1d60, 0x140002743c0})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:905 +0x490
github.com/goccy/go-yaml.(*Decoder).decodeValue(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x105ddb100?, 0x14000278318?, 0x1?}, {0x1061b1d60, 0x140002743c0})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:980 +0x1394
github.com/goccy/go-yaml.(*Decoder).createDecodedNewValue(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x1061bf080, 0x105ddb100}, {0x105ddb100?, 0x140003a3b70?, 0x11?}, {0x1061b1d60, 0x140002743c0})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1180 +0x2b8
github.com/goccy/go-yaml.(*Decoder).decodeStruct(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x1060ba7e0?, 0x140003a3b20?, 0x14000095300?}, {0x1061b1c60, 0x14000248c00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1497 +0xa2c
github.com/goccy/go-yaml.(*Decoder).decodeValue(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x1060ba7e0?, 0x140003a3b20?, 0x1400024a510?}, {0x1061b1c60, 0x14000248c00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1031 +0x11f8
github.com/goccy/go-yaml.(*Decoder).decode(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x105e40780?, 0x140003a3b20?, 0x14000100008?})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1995 +0xa0
github.com/goccy/go-yaml.(*Decoder).DecodeContext(0x140000c2410, {0x1061a5630, 0x1070b3c00}, {0x105e40780?, 0x140003a3b20?})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:2030 +0x184
github.com/goccy/go-yaml.(*Decoder).Decode(...)
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:2008
github.com/googleapis/genai-toolbox/internal/server.(*ToolConfigs).UnmarshalYAML(0x14000094c48, 0x140000376b0)
        /workspace/internal/server/config.go:315 +0x534
github.com/goccy/go-yaml.(*Decoder).decodeByUnmarshaler(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x105e3ae00?, 0x14000094c48?, 0xc?}, {0x1061b1c60, 0x14000178d00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:905 +0x490
github.com/goccy/go-yaml.(*Decoder).decodeValue(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x105e3ae00?, 0x14000094c48?, 0x1?}, {0x1061b1c60, 0x14000178d00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:980 +0x1394
github.com/goccy/go-yaml.(*Decoder).createDecodedNewValue(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x1061bf080, 0x105e3ae00}, {0x105e3ae00?, 0x1400045b8f0?, 0xc?}, {0x1061b1c60, 0x14000178d00})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1180 +0x2b8
github.com/goccy/go-yaml.(*Decoder).decodeStruct(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x105fef0c0?, 0x1400045b8e0?, 0x14000094b78?}, {0x1061b1c60, 0x14000178a80})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1497 +0xa2c
github.com/goccy/go-yaml.(*Decoder).decodeValue(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x105fef0c0?, 0x1400045b8e0?, 0x1400068e660?}, {0x1061b1c60, 0x14000178a80})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1031 +0x11f8
github.com/goccy/go-yaml.(*Decoder).decode(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x105cf2220?, 0x1400045b8e0?, 0x1049a25fc?})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:1995 +0xa0
github.com/goccy/go-yaml.(*Decoder).DecodeContext(0x14000341ba0, {0x1061a5630, 0x1070b3c00}, {0x105cf2220?, 0x1400045b8e0?})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/decode.go:2030 +0x184
github.com/goccy/go-yaml.UnmarshalContext({0x1061a5630, 0x1070b3c00}, {0x14000356c00, 0xb9a, 0xb9b}, {0x105cf2220, 0x1400045b8e0}, {0x140000948d0, 0x1, 0x1})
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/yaml.go:190 +0x208
github.com/goccy/go-yaml.UnmarshalWithOptions(...)
        /gopath/pkg/mod/github.com/goccy/go-yaml@v1.15.13/yaml.go:184
github.com/googleapis/genai-toolbox/cmd.parseToolsFile({0x14000356c00, 0xb9a, 0xb9b})
        /workspace/cmd/root.go:131 +0x84
github.com/googleapis/genai-toolbox/cmd.run(0x140003f81c0)
        /workspace/cmd/root.go:202 +0x614
github.com/googleapis/genai-toolbox/cmd.NewCommand.func1(0x140001c3000?, {0x105947b29?, 0x7?, 0x10593dfa4?})
        /workspace/cmd/root.go:115 +0x20
github.com/spf13/cobra.(*Command).execute(0x14000371508, {0x1400004c5e0, 0x2, 0x2})
        /gopath/pkg/mod/github.com/spf13/cobra@v1.8.1/command.go:985 +0x834
github.com/spf13/cobra.(*Command).ExecuteC(0x14000371508)
        /gopath/pkg/mod/github.com/spf13/cobra@v1.8.1/command.go:1117 +0x344
github.com/spf13/cobra.(*Command).Execute(...)
        /gopath/pkg/mod/github.com/spf13/cobra@v1.8.1/command.go:1041
github.com/googleapis/genai-toolbox/cmd.Execute()
        /workspace/cmd/root.go:59 +0x30
main.main()
        /workspace/main.go:20 +0x1c
```



Fix (patch):
diff --git a/internal/util/util.go b/internal/util/util.go
index ab4642854e5..5daef2678cd 100644
--- a/internal/util/util.go
+++ b/internal/util/util.go
@@ -36,6 +36,9 @@ func (d *DelayedUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) er
 }
 
 func (d *DelayedUnmarshaler) Unmarshal(v interface{}) error {
+	if d.unmarshal == nil {
+		return fmt.Errorf("nothing to unmarshal")
+	}
 	return d.unmarshal(v)
 }