{"record":{"id":"f592d1f438ff811e","repo":"JuliusBrussee/caveman","slug":"duplicate-s","errorCode":null,"errorMessage":"duplicate %s","messagePattern":"duplicate (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/cmd/caveman-proxy/stats.go","lineNumber":24,"sourceCode":"\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/JuliusBrussee/caveman/proxy/internal/store\"\n)\n\n// The richer report is explicitly selected. Existing stats --json callers\n// (telemetry and session footers) keep their original schema and behavior.\nfunc parseStatsReportOptions(args []string) (store.StatsReportOptions, bool, string, error) {\n\topts := store.StatsReportOptions{Days: 30, Now: time.Now()}\n\twriteReport, out := false, \"\"\n\tseen := map[string]bool{}\n\tfor i := 0; i < len(args); i++ {\n\t\targ := args[i]\n\t\tif seen[arg] {\n\t\t\treturn opts, false, \"\", fmt.Errorf(\"duplicate %s\", arg)\n\t\t}\n\t\tseen[arg] = true\n\t\tswitch arg {\n\t\tcase \"--report\", \"--json\":\n\t\tcase \"--write-report\":\n\t\t\twriteReport = true\n\t\tcase \"--days\", \"--provider\", \"--model\", \"--agent\", \"--auth\", \"--out\":\n\t\t\ti++\n\t\t\tif i >= len(args) || args[i] == \"\" || strings.HasPrefix(args[i], \"--\") || strings.ContainsAny(args[i], \"\\x00\\r\\n\") {\n\t\t\t\treturn opts, false, \"\", fmt.Errorf(\"%s requires a value\", arg)\n\t\t\t}\n\t\t\tvalue := args[i]\n\t\t\tswitch arg {\n\t\t\tcase \"--days\":\n\t\t\t\tdays, err := strconv.Atoi(value)\n\t\t\t\tif err != nil || days < 0 || days > 3660 {\n\t\t\t\t\treturn opts, false, \"\", fmt.Errorf(\"--days must be an integer from 0 to 3660\")\n\t\t\t\t}","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/cmd/caveman-proxy/stats.go#L6-L42","documentation":"parseStatsReportOptions (proxy/cmd/caveman-proxy/stats.go:24) parses the flags for the stats report command and enforces that each option appears at most once, tracking them in a seen map. Repeating any recognized or unrecognized option — even with the same value — is rejected as 'duplicate <arg>'. This keeps the report configuration unambiguous.","triggerScenarios":"Running the stats command with the same flag twice, e.g. 'stats --days 7 --days 30' or '--report --report'. The second occurrence hits seen[arg]==true and returns this error.","commonSituations":"Shell scripts appending flags conditionally and repeating one; copy-pasting a command line where a flag was already present; aliases or wrappers that inject default flags the user also typed.","solutions":["Remove the duplicated flag, keeping a single occurrence with the desired value","Audit wrapper scripts/aliases that may inject the same flag the user also supplies","Remember the rule applies to every option string, including boolean --report/--json"],"exampleFix":"// before\ncaveman-proxy stats --days 7 --days 30 --report\n// after\ncaveman-proxy stats --days 30 --report","handlingStrategy":"validation","validationCode":"function assertNoDuplicateFlags(args) {\n  const seen = new Set();\n  for (const a of args.filter(x => x.startsWith(\"--\"))) {\n    if (seen.has(a)) throw new Error(`duplicate flag ${a}`);\n    seen.add(a);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build command lines from arrays/dicts keyed by flag name so duplicates are impossible","Audit wrapper scripts that append default flags","Review the final argv before invoking stats in shell scripts"],"tags":["cli","duplicate-flag","argument-parsing","stats"],"backgroundTag":"conflicting-config-options","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}