Part of duplicate code analysis: #10043
Summary
In internal/config/validation_gateway.go and internal/config/validation_server.go, the pattern of null-checking an optional pointer field before dereferencing and validating it is repeated ~12 times with identical structure. Each instance looks like:
if field != nil {
logValidation.Printf("Validating X: %v", *field)
if err := ValidateRule(*field, "fieldName", "json.path"); err != nil {
return err
}
}
No shared helper exists to encapsulate this pattern.
Duplication Details
Pattern: if ptr != nil { validate(*ptr) } guard in config validation
// validation_gateway.go:26-31
if gateway.StartupTimeout != nil {
logValidation.Printf("Validating startup timeout: %d", *gateway.StartupTimeout)
if err := TimeoutPositive(*gateway.StartupTimeout, "startupTimeout", "gateway.startupTimeout"); err != nil {
return err
}
}
// validation_gateway.go:33-38
if gateway.ToolTimeout != nil {
logValidation.Printf("Validating tool timeout: %d", *gateway.ToolTimeout)
if err := TimeoutMinimum(*gateway.ToolTimeout, ToolTimeoutMin, "toolTimeout", "gateway.toolTimeout"); err != nil {
return err
}
}
// validation_gateway.go:18-23
if gateway.Port != nil {
logValidation.Printf("Validating gateway port: %d", *gateway.Port)
if err := PortRange(*gateway.Port, "gateway.port"); err != nil {
return err
}
}
Impact Analysis
- Maintainability: Adding a new optional field to
StdinGatewayConfig or StdinServerConfig requires adding another copy of this boilerplate pattern rather than registering a validation rule.
- Bug Risk: If a new field is added but the nil-guard is accidentally omitted, it will panic at
*field when the field is absent.
- Code Bloat: The repeated structure inflates the validation functions and makes them harder to scan.
Refactoring Recommendations
-
Add a generic validateOptionalInt helper (or use a validationRule slice approach)
// In validation_shared.go or validation_rules.go
func validateOptionalInt(ptr *int, logMsg string, validateFn func(int) *ValidationError) error {
if ptr == nil {
return nil
}
logValidation.Print(logMsg)
return validateFn(*ptr)
}
Usage:
if err := validateOptionalInt(gateway.StartupTimeout, "Validating startup timeout",
func(v int) *ValidationError { return TimeoutPositive(v, "startupTimeout", "gateway.startupTimeout") }); err != nil {
return err
}
-
Alternatively, use a declarative validation rule list that maps field names to validators, which is iterated in a single loop.
- Estimated effort: 2–4 hours
- Benefits: new optional fields need only a one-line entry, nil-check safety is centralized
Implementation Checklist
Parent Issue
See parent analysis report: #10043
Related to #10043
Generated by Duplicate Code Detector · sonnet46 · 101 AIC · ⊞ 9.1K · ◷
Part of duplicate code analysis: #10043
Summary
In
internal/config/validation_gateway.goandinternal/config/validation_server.go, the pattern of null-checking an optional pointer field before dereferencing and validating it is repeated ~12 times with identical structure. Each instance looks like:No shared helper exists to encapsulate this pattern.
Duplication Details
Pattern:
if ptr != nil { validate(*ptr) }guard in config validationSeverity: Medium
Occurrences: ~12 instances across 2 files
Locations:
internal/config/validation_gateway.go(lines 18–22, 26–31, 33–38, 60–63)internal/config/validation_server.go(lines 88–92)Code Sample:
Impact Analysis
StdinGatewayConfigorStdinServerConfigrequires adding another copy of this boilerplate pattern rather than registering a validation rule.*fieldwhen the field is absent.Refactoring Recommendations
Add a generic
validateOptionalInthelper (or use avalidationRuleslice approach)Usage:
Alternatively, use a declarative validation rule list that maps field names to validators, which is iterated in a single loop.
Implementation Checklist
validateOptionalInt(or similar) helper tointernal/config/validation_rules.govalidateGatewayConfiginvalidation_gateway.goto use itvalidateStandardServerConfiginvalidation_server.goto use itParent Issue
See parent analysis report: #10043
Related to #10043