Skip to content

[duplicate-code] Duplicate Code Pattern: Optional Pointer Field Validation Guard in Config #10044

Description

@github-actions

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

  • Severity: 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:

// 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

  1. 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
    }
  2. 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

  • Review duplication findings
  • Add validateOptionalInt (or similar) helper to internal/config/validation_rules.go
  • Refactor validateGatewayConfig in validation_gateway.go to use it
  • Refactor validateStandardServerConfig in validation_server.go to use it
  • Update tests if needed
  • Verify no functionality broken

Parent Issue

See parent analysis report: #10043
Related to #10043

Generated by Duplicate Code Detector · sonnet46 · 101 AIC · ⊞ 9.1K ·

  • expires on Aug 1, 2026, 3:38 AM UTC

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions