Skip to content

[duplicate-code] Duplicate Code Pattern: Repeated ValidationError Construction in MountFormat (6 instances) #8173

Description

@github-actions

🔍 Duplicate Code Pattern: Repeated ValidationError Construction in MountFormat

Part of duplicate code analysis: #8170

Summary

The MountFormat function in internal/config/validation_rules.go constructs &ValidationError{Field: "mounts", JSONPath: fmt.Sprintf("%s.mounts[%d]", jsonPath, index), ...} six times with the same Field and JSONPath formula — only the Message and Suggestion fields differ. A small private factory helper would eliminate ~36 lines of repetition.

Duplication Details

Pattern: Repeated &ValidationError struct literal with identical Field and JSONPath

  • Severity: High
  • Occurrences: 6 instances
  • Location: internal/config/validation_rules.goMountFormat function (lines ~95–156)

Representative repeated block (one of six):

return &ValidationError{
    Field:      "mounts",
    Message:    fmt.Sprintf("invalid mount format '%s' (expected 'source:dest:mode')", mount),
    JSONPath:   fmt.Sprintf("%s.mounts[%d]", jsonPath, index),
    Suggestion: "Use format 'source:dest:mode' where mode is 'ro' (read-only) or 'rw' (read-write)...",
}

All six return statements share:

  • Field: "mounts"constant, never varies
  • JSONPath: fmt.Sprintf("%s.mounts[%d]", jsonPath, index)formula, never varies

The only varying parts are Message (describes the specific validation failure) and Suggestion (remediation hint).

All six call-sites in MountFormat:

Line Condition checked Unique Message
~95 len(parts) != 3 "invalid mount format '%s' (expected 'source:dest:mode')"
~110 source path empty "mount source cannot be empty in '%s'"
~120 source not absolute "mount source must be an absolute path in '%s'"
~129 dest path empty "mount destination cannot be empty in '%s'"
~139 dest not absolute "mount destination must be an absolute path in '%s'"
~150 invalid mode "invalid mount mode '%s' (expected 'ro' or 'rw')"

Impact Analysis

  • Maintainability: Adding a new mount validation error (e.g., checking for path traversal) requires copy-pasting the full 6-line struct literal again
  • Bug Risk: If the JSONPath formula changes (e.g., spec requires a different path format), all 6 sites must be updated — easy to miss one
  • Code Bloat: ~36 lines reducible to ~6 call-sites (factor of 6 reduction)

Refactoring Recommendations

1. Extract private mountValidationError factory

Add a private helper inside validation_rules.go:

// mountValidationError creates a ValidationError for mount validation failures.
// The Field and JSONPath are always the same for mount errors; only message
// and suggestion vary between the different validation checks.
func mountValidationError(jsonPath string, index int, message, suggestion string) *ValidationError {
    return &ValidationError{
        Field:      "mounts",
        Message:    message,
        JSONPath:   fmt.Sprintf("%s.mounts[%d]", jsonPath, index),
        Suggestion: suggestion,
    }
}

Six call-sites in MountFormat become:

// Before (6 lines each):
return &ValidationError{
    Field:   "mounts",
    Message: fmt.Sprintf("invalid mount format '%s' (expected 'source:dest:mode')", mount),
    JSONPath: fmt.Sprintf("%s.mounts[%d]", jsonPath, index),
    Suggestion: "Use format ...",
}

// After (1 line each):
return mountValidationError(jsonPath, index,
    fmt.Sprintf("invalid mount format '%s' (expected 'source:dest:mode')", mount),
    "Use format 'source:dest:mode' where mode is 'ro' (read-only) or 'rw' (read-write)...")

Implementation Checklist

  • Add mountValidationError private helper to internal/config/validation_rules.go
  • Replace all 6 &ValidationError{Field: "mounts", ...} literals in MountFormat with calls to the helper
  • Run make test to verify no behavior change
  • Check make lint passes

Parent Issue

See parent analysis report: #8170
Related to #8170

Generated by Duplicate Code Detector · 936.3 AIC · ⊞ 35.7K ·

  • expires on Jul 4, 2026, 3:46 AM UTC

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions