You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
github.com/santhosh-tekuri/jsonschema/v6 is a Go implementation of JSON Schema validation supporting Draft 4, Draft 6, Draft 7, Draft 2019-09, and Draft 2020-12 β the latest and most capable dialect. It is used in this project to validate MCP Gateway configuration against a bundled JSON Schema document at startup and at request time.
ErrorKind.LocalizedString(printer) β i18n-aware error messages via golang.org/x/text
Usage Patterns
Pattern
Status
Embedded schema via go:embed
β Implemented
sync.Once compile-once caching
β Implemented
jsonschema.UnmarshalJSON for number precision
β Implemented
Type-switch on kind.* for error dispatch
β Implemented
Recursive ve.Causes traversal
β Implemented
Localized error messages
β Implemented
Remote schema caching via sync.Map
β Implemented
HTTPS enforcement for remote schemas
β Implemented
IO size-bounded remote fetch (io.LimitReader)
β Implemented
Research Findings
The project makes excellent, idiomatic use of this library. It follows the recommended patterns from the upstream README:
Use UnmarshalJSON (not encoding/json) to avoid number precision issues
Compile schemas once and reuse (the project uses sync.Once)
Use the kind sub-package for typed error introspection
Best Practices in Use
The compiler defaults to Draft 2020-12 (the library default since v6), which is the most capable dialect
The embedded schema eliminates network dependency at startup
Both the compiled schema and compilation errors are cached so failed compilations are not retried endlessly
Improvement Opportunities
π Quick Wins
1. Stale draft version hint in error message
In internal/config/validation_server.go line 305, a compile-failure error message says:
"The schema at '%s' must be a valid JSON Schema Draft 7 document"
But the compiler is created via jsonschema.NewCompiler() which defaults to Draft 2020-12, not Draft 7. This misleads users when their remote custom schema fails to compile.
Fix: Update the hint to say "valid JSON Schema document (Draft 2020-12 or earlier)" or simply "valid JSON Schema document".
2. fmt.Errorf("%s", sb.String()) anti-pattern
In internal/config/validation_schema.go line 252:
returnfmt.Errorf("%s", sb.String())
This is a misuse of fmt.Errorf when there is no actual %w error wrapping and no format verbs on an error value. Prefer:
returnerrors.New(sb.String())
This avoids the go vet / golangci-lint suggestion about using errors.New for static string errors and is more idiomatic.
β¨ Feature Opportunities
1. Schema draft auto-detection for custom schemas
The library supports multiple drafts β if custom schemas submitted by users target Draft 7 (a common default for many toolchains), they may fail compilation or produce confusing errors under the Draft 2020-12 compiler. Consider documenting the expected draft version in error messages or calling compiler.SetDefaultDraft() when compiling custom (remote) schemas.
2. Structured error output for machine consumers
Currently formatSchemaError returns a human-readable string. For programmatic clients (e.g., Copilot agents consuming config validation errors), a structured JSON error representation would be more useful. The ValidationError tree is already available and could be serialized alongside the human-readable message.
3. Expand formatErrorContext for additional kind.* types
The kind sub-package includes more constraint types than are currently handled (e.g., UniqueItems, Contains, ContentMediaType, If/Then/Else). Periodic review of new kind.* additions could improve error guidance for users hitting those constraints.
π Best Practice Alignment
1. Number precision in validateServerAgainstSchema
In validateServerAgainstSchema, the server config is validated via json.Marshal β json.Unmarshal into map[string]interface{} before passing to schema.Validate. This round-trip could theoretically lose number precision for large integers or high-precision floats. For consistency with the embedded schema validation path, consider using jsonschema.UnmarshalJSON on the marshalled bytes instead of encoding/json.Unmarshal.
// Current:json.Unmarshal(serverJSON, &serverMap)
// Suggested:serverObj, parseErr:=jsonschema.UnmarshalJSON(bytes.NewReader(serverJSON))
// then use serverObj directly in schema.Validate()
2. newCompiler() options for extensibility
Currently newCompiler() takes no parameters. If draft pinning or vocabulary configuration is ever needed (e.g., to handle legacy Draft 7 custom schemas), accepting functional options would make this easy to extend without breaking callers.
π§ General Improvements
1. Consider compiler.UseLoader for remote schema management
The library supports a UseLoader mechanism for pluggable resource loading. The current implementation manually fetches remote schemas (with retries, size limits) and manages a sync.Map cache. Using UseLoader could centralize the HTTP fetch + caching logic, make it easier to test with mock loaders, and align with library conventions.
2. Test coverage for the unknown ErrorKind default path
The switch ve.ErrorKind.(type) in formatErrorContext has an implicit default no-op path for unrecognised kind.* types (returning an empty string). There is no test verifying this behavior. A simple test case would catch any future regression if an unknown kind accidentally matched a case.
Fix the misleading Draft 7 error hint in validateAgainstCustomSchema (validation_server.go:305) β change to "valid JSON Schema document (Draft 2020-12 or earlier)"(trivial, high clarity value)
Replace fmt.Errorf("%s", sb.String()) with errors.New(sb.String()) in formatSchemaError (validation_schema.go:252) (trivial cleanup)
Add a test for the unknown ErrorKind default path in TestFormatErrorContext(low effort, prevents regression)
Use jsonschema.UnmarshalJSON in validateServerAgainstSchema for number-precision consistency with the embedded schema path (medium effort, improves correctness)
Evaluate compiler.UseLoader as a potential simplification for the remote schema fetch/cache flow (future enhancement)
Next Steps
Fix the Draft 7 hint text in validation_server.go:305
Replace fmt.Errorf("%s", ...) with errors.New() in validation_schema.go:252
Add a test for the unknown-kind default path in TestFormatErrorContext
Explore compiler.UseLoader as a potential simplification
πΉ Go Fan Report: santhosh-tekuri/jsonschema/v6
Module Overview
github.com/santhosh-tekuri/jsonschema/v6is a Go implementation of JSON Schema validation supporting Draft 4, Draft 6, Draft 7, Draft 2019-09, and Draft 2020-12 β the latest and most capable dialect. It is used in this project to validate MCP Gateway configuration against a bundled JSON Schema document at startup and at request time.Current Usage in gh-aw
kindsub-package)jsonschema.NewCompiler()β creates a Draft 2020-12 compilerjsonschema.UnmarshalJSON()β precision-safe JSON parsingcompiler.AddResource()β registers schemas by URLcompiler.Compile()β compiles a schema for reuseschema.Validate()β validates a parsed document*jsonschema.ValidationError+ve.Causes,ve.InstanceLocation,ve.ErrorKindβ rich error tree traversalkind.*types (AdditionalProperties,Type,Enum,Required,Pattern,OneOf, etc.) β typed error dispatchErrorKind.LocalizedString(printer)β i18n-aware error messages viagolang.org/x/textUsage Patterns
go:embedsync.Oncecompile-once cachingjsonschema.UnmarshalJSONfor number precisionkind.*for error dispatchve.Causestraversalsync.Mapio.LimitReader)Research Findings
The project makes excellent, idiomatic use of this library. It follows the recommended patterns from the upstream README:
UnmarshalJSON(notencoding/json) to avoid number precision issuessync.Once)kindsub-package for typed error introspectionBest Practices in Use
Improvement Opportunities
π Quick Wins
1. Stale draft version hint in error message
In
internal/config/validation_server.goline 305, a compile-failure error message says:But the compiler is created via
jsonschema.NewCompiler()which defaults to Draft 2020-12, not Draft 7. This misleads users when their remote custom schema fails to compile.Fix: Update the hint to say
"valid JSON Schema document (Draft 2020-12 or earlier)"or simply"valid JSON Schema document".2.
fmt.Errorf("%s", sb.String())anti-patternIn
internal/config/validation_schema.goline 252:This is a misuse of
fmt.Errorfwhen there is no actual%werror wrapping and no format verbs on an error value. Prefer:This avoids the
go vet/golangci-lintsuggestion about usingerrors.Newfor static string errors and is more idiomatic.β¨ Feature Opportunities
1. Schema draft auto-detection for custom schemas
The library supports multiple drafts β if custom schemas submitted by users target Draft 7 (a common default for many toolchains), they may fail compilation or produce confusing errors under the Draft 2020-12 compiler. Consider documenting the expected draft version in error messages or calling
compiler.SetDefaultDraft()when compiling custom (remote) schemas.2. Structured error output for machine consumers
Currently
formatSchemaErrorreturns a human-readable string. For programmatic clients (e.g., Copilot agents consuming config validation errors), a structured JSON error representation would be more useful. TheValidationErrortree is already available and could be serialized alongside the human-readable message.3. Expand
formatErrorContextfor additionalkind.*typesThe
kindsub-package includes more constraint types than are currently handled (e.g.,UniqueItems,Contains,ContentMediaType,If/Then/Else). Periodic review of newkind.*additions could improve error guidance for users hitting those constraints.π Best Practice Alignment
1. Number precision in
validateServerAgainstSchemaIn
validateServerAgainstSchema, the server config is validated viajson.Marshalβjson.Unmarshalintomap[string]interface{}before passing toschema.Validate. This round-trip could theoretically lose number precision for large integers or high-precision floats. For consistency with the embedded schema validation path, consider usingjsonschema.UnmarshalJSONon the marshalled bytes instead ofencoding/json.Unmarshal.2.
newCompiler()options for extensibilityCurrently
newCompiler()takes no parameters. If draft pinning or vocabulary configuration is ever needed (e.g., to handle legacy Draft 7 custom schemas), accepting functional options would make this easy to extend without breaking callers.π§ General Improvements
1. Consider
compiler.UseLoaderfor remote schema managementThe library supports a
UseLoadermechanism for pluggable resource loading. The current implementation manually fetches remote schemas (with retries, size limits) and manages async.Mapcache. UsingUseLoadercould centralize the HTTP fetch + caching logic, make it easier to test with mock loaders, and align with library conventions.2. Test coverage for the unknown
ErrorKinddefault pathThe
switch ve.ErrorKind.(type)informatErrorContexthas an implicit default no-op path for unrecognisedkind.*types (returning an empty string). There is no test verifying this behavior. A simple test case would catch any future regression if an unknown kind accidentally matched a case.Module Summary
github.com/santhosh-tekuri/jsonschema/v6v6.0.2Key Features
UnmarshalJSONfor precision-safe JSON parsingkind.*error introspection sub-packageErrorKind.LocalizedString(printer)AddResource/Compilefor schema composition and$refresolutionReferences
Recommendations
validateAgainstCustomSchema(validation_server.go:305) β change to"valid JSON Schema document (Draft 2020-12 or earlier)"(trivial, high clarity value)fmt.Errorf("%s", sb.String())witherrors.New(sb.String())informatSchemaError(validation_schema.go:252) (trivial cleanup)ErrorKinddefault path inTestFormatErrorContext(low effort, prevents regression)jsonschema.UnmarshalJSONinvalidateServerAgainstSchemafor number-precision consistency with the embedded schema path (medium effort, improves correctness)compiler.UseLoaderas a potential simplification for the remote schema fetch/cache flow (future enhancement)Next Steps
validation_server.go:305fmt.Errorf("%s", ...)witherrors.New()invalidation_schema.go:252TestFormatErrorContextcompiler.UseLoaderas a potential simplificationGenerated by Go Fan πΉ Β· Run Β§29398122955
References:
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
awmgmcpgSee Network Configuration for more information.