Пример
sigs.k8s.io/yaml v1.6.0: Distinguish sigs.k8s.io/yaml error paths where type mismatch returns a wrapped json.UnmarshalTypeError instead of yaml.TypeError, non-pointer destination returns nil without error, and UnmarshalStrict splits errors between YAML conversion and JSON decoding
Проверенный пример — golang sigs.k8s.io/yaml v1.6.0: Distinguish sigs.k8s.io/yaml error paths where type mismatch returns a wrapped json.UnmarshalTypeError…
sha256:f533a87bcb9bdba83dcdf7f1d6a19bb8a0a9e2fc9865878a545c8ff434c356e7
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
MIT-0
Свидетельства выполнения
Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.
- Основа свидетельства
- Подписанный контракт пройден
- Квитанции проверки
- 3
- Ключи подписи, собравшие его
- 3
Заявленная среда
go linux x64 go go go
Среды запусков проверки
| Окружение | Контракт | Этапы | Запуск |
|---|---|---|---|
| go 1.26 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · golang@1 |
2026-08-16 |
| go 1.26 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · golang@1 |
2026-08-18 |
| go 1.26 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · golang@1golang:1.26-alpine@sha256:28d89ee9cc0f… |
2026-09-08 |
Кейс
HOW- Цель
- Distinguish sigs.k8s.io/yaml error paths where type mismatch returns a wrapped json.UnmarshalTypeError instead of yaml.TypeError, non-pointer destination returns nil without error, and UnmarshalStrict splits errors between YAML conversion and JSON decoding
- Пакеты
- Символы
-
- sigs.k8s.io/yaml.Unmarshal
- sigs.k8s.io/yaml.UnmarshalStrict
- Окружение
- go
- Создан
- 2026-08-16T13:28:01Z
Контракт
- Type mismatch in YAML unmarshaling returns a wrapped *json.UnmarshalTypeError with prefix 'error unmarshaling JSON' and does not match yaml.TypeError
- Passing a non-pointer value to Unmarshal silently returns nil instead of returning *json.InvalidUnmarshalError or panicking, leaving the target struct unmodified
- UnmarshalStrict returns 'error converting YAML to JSON' for duplicate keys but 'error unmarshaling JSON' for unknown struct fields
Файлы
- NOTES.md
- csx.json
- go.mod
- go.sum
- yaml_error_test.go
Исходный код
# sigs.k8s.io/yaml Error Handling Behavior
## Search Result
`search_known_solution` returned sample `sha256:03d14e2883c81e3c8dd5a947bbd6bf84b0c7682b5e2b5e0adf9b88c3287d4652` ("Decode YAML with sigs.k8s.io/yaml where json tags take precedence and yaml tags are ignored unlike yaml.v3").
## Error Path Behavior
`sigs.k8s.io/yaml` decodes YAML documents by first converting them to intermediate JSON objects and then invoking standard library `encoding/json.NewDecoder`. This layered decoding architecture produces distinct error behaviors across input violations:
- Struct field type mismatches return a wrapped `*json.UnmarshalTypeError` prefixed with `error unmarshaling JSON: while decoding JSON: json: `, rather than a `yaml.TypeError`. Callers asserting on `yaml.TypeError` or expecting YAML-attributed error strings fail loudly with runtime mismatches.
- Passing a non-pointer destination argument to `yaml.Unmarshal` does not return `*json.InvalidUnmarshalError` and does not panic; it decodes into a temporary interface pointer and silently returns `nil`, leaving the caller's struct unpopulated with a green build.
- `yaml.UnmarshalStrict` bifurcates error reporting: duplicate YAML keys fail in the conversion step (`error converting YAML to JSON: yaml: ...`), whereas unknown struct fields fail in the JSON decoding step (`error unmarshaling JSON: while decoding JSON: json: unknown field ...`).
{"case":{"believed":"Unmarshaling YAML with type mismatches returns a yaml.TypeError, non-pointer destinations return an InvalidUnmarshalError, and UnmarshalStrict returns uniform YAML unmarshal errors for all schema violations.","caseId":"case:sha256:b652f00a86ff1ddd541ba33cf3320ec1ae1076f63d3367291150f7e9b831a53a","contract":["Type mismatch in YAML unmarshaling returns a wrapped *json.UnmarshalTypeError with prefix 'error unmarshaling JSON' and does not match yaml.TypeError","Passing a non-pointer value to Unmarshal silently returns nil instead of returning *json.InvalidUnmarshalError or panicking, leaving the target struct unmodified","UnmarshalStrict returns 'error converting YAML to JSON' for duplicate keys but 'error unmarshaling JSON' for unknown struct fields"],"goal":"Distinguish sigs.k8s.io/yaml error paths where type mismatch returns a wrapped json.UnmarshalTypeError instead of yaml.TypeError, non-pointer destination returns nil without error, and UnmarshalStrict splits errors between YAML conversion and JSON decoding","kind":"HOW","packages":["pkg:golang/sigs.k8s.io/yaml@1.6.0"],"schemaVersion":1,"symbols":["sigs.k8s.io/yaml.Unmarshal","sigs.k8s.io/yaml.UnmarshalStrict"]},"contractCommand":["go","test","./..."],"environment":{"arch":"x64","ecosystem":"golang","executionContext":"go","language":"go","os":"linux","packageManager":"go","runtime":"go","schemaVersion":1},"license":"MIT-0","packages":["pkg:golang/sigs.k8s.io/yaml@1.6.0"],"schemaVersion":1,"symbols":["sigs.k8s.io/yaml.Unmarshal","sigs.k8s.io/yaml.UnmarshalStrict"],"verifierAdapter":"golang@1"}
module sample
go 1.22
require (
go.yaml.in/yaml/v2 v2.4.2
sigs.k8s.io/yaml v1.6.0
)
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
package sample
import (
"encoding/json"
"errors"
"strings"
"testing"
yamlv2 "go.yaml.in/yaml/v2"
"sigs.k8s.io/yaml"
)
type ServerConfig struct {
Host string `json:"host"`
Port int `json:"port"`
}
func TestTypeMismatchReturnsJSONError(t *testing.T) {
input := []byte("host: example.com\nport: not_a_number\n")
var cfg ServerConfig
err := yaml.Unmarshal(input, &cfg)
if err == nil {
t.Fatal("expected type mismatch error, got nil")
}
var jsonErr *json.UnmarshalTypeError
if !errors.As(err, &jsonErr) {
t.Fatalf("expected errors.As json.UnmarshalTypeError to be true, got err: %v (%T)", err, err)
}
if jsonErr.Field != "port" {
t.Fatalf("expected jsonErr.Field to be 'port', got %q", jsonErr.Field)
}
var yamlErr *yamlv2.TypeError
if errors.As(err, &yamlErr) {
t.Fatal("expected errors.As yaml.TypeError to be false, got true")
}
expectedPrefix := "error unmarshaling JSON: while decoding JSON: json: "
if !strings.HasPrefix(err.Error(), expectedPrefix) {
t.Fatalf("expected error to start with %q, got %q", expectedPrefix, err.Error())
}
}
func TestNonPointerTargetSilentlyReturnsNil(t *testing.T) {
input := []byte("host: example.com\nport: 8080\n")
var cfg ServerConfig
err := yaml.Unmarshal(input, cfg)
if err != nil {
t.Fatalf("expected yaml.Unmarshal with non-pointer to return nil, got: %v", err)
}
if cfg.Host != "" || cfg.Port != 0 {
t.Fatalf("expected cfg to remain zero-valued, got: %+v", cfg)
}
jsonInput := []byte(`{"host":"example.com","port":8080}`)
var jsonCfg ServerConfig
jErr := json.Unmarshal(jsonInput, jsonCfg)
var invErr *json.InvalidUnmarshalError
if !errors.As(jErr, &invErr) {
t.Fatalf("expected json.Unmarshal with non-pointer to return *json.InvalidUnmarshalError, got: %v", jErr)
}
}
func TestStrictDecodingErrorDivergence(t *testing.T) {
var cfg ServerConfig
dupInput := []byte("host: example.com\nport: 8080\nport: 9090\n")
errDup := yaml.UnmarshalStrict(dupInput, &cfg)
if errDup == nil {
t.Fatal("expected duplicate key error from UnmarshalStrict, got nil")
}
expectedDupPrefix := "error converting YAML to JSON: yaml: "
if !strings.HasPrefix(errDup.Error(), expectedDupPrefix) {
t.Fatalf("expected duplicate key error to start with %q, got %q", expectedDupPrefix, errDup.Error())
}
unknownInput := []byte("host: example.com\nport: 8080\nextra_field: true\n")
errUnknown := yaml.UnmarshalStrict(unknownInput, &cfg)
if errUnknown == nil {
t.Fatal("expected unknown field error from UnmarshalStrict, got nil")
}
expectedUnknownPrefix := "error unmarshaling JSON: while decoding JSON: json: unknown field"
if !strings.HasPrefix(errUnknown.Error(), expectedUnknownPrefix) {
t.Fatalf("expected unknown field error to start with %q, got %q", expectedUnknownPrefix, errUnknown.Error())
}
}