{"record":{"id":"6eb9cd89e49a859c","repo":"jdx/mise","slug":"trimv-requires-exactly-1-argument","errorCode":null,"errorMessage":"trimV requires exactly 1 argument","messagePattern":"trimV requires exactly 1 argument","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"crates/aqua-registry/src/template.rs","lineNumber":358,"sourceCode":"\n        Ok(Box::new(SemVerValue {\n            major: version.nth(0).unwrap_or(0),\n            minor: version.nth(1).unwrap_or(0),\n            patch: version.nth(2).unwrap_or(0),\n            original: clean_version.to_string(),\n        }) as Box<dyn Value>)\n    });\n\n    registry.insert(\"title\", |args| {\n        if args.len() != 1 {\n            bail!(\"title requires exactly 1 argument\");\n        }\n        Ok(Box::new(StringValue(args[0].as_string().to_title_case())) as Box<dyn Value>)\n    });\n\n    registry.insert(\"trimV\", |args| {\n        if args.len() != 1 {\n            bail!(\"trimV requires exactly 1 argument\");\n        }\n        Ok(Box::new(StringValue(\n            args[0].as_string().trim_start_matches('v').to_string(),\n        )) as Box<dyn Value>)\n    });\n\n    registry.insert(\"trimPrefix\", |args| {\n        if args.len() != 2 {\n            bail!(\"trimPrefix requires exactly 2 arguments\");\n        }\n        let prefix = args[0].as_string();\n        let text = args[1].as_string();\n        Ok(Box::new(StringValue(\n            text.strip_prefix(&prefix).unwrap_or(&text).to_string(),\n        )) as Box<dyn Value>)\n    });\n\n    registry.insert(\"trimSuffix\", |args| {","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/crates/aqua-registry/src/template.rs#L340-L376","documentation":"command_wrapper's content and executable are mutually exclusive: content is written verbatim as the launcher script, while executable generates a shell wrapper around the binary. Setting both is ambiguous and rejected at parse time.","triggerScenarios":"Options object containing both 'content' and 'executable' keys, e.g. while migrating a wrapper from inline script to binary wrapping and forgetting to remove the old key.","commonSituations":"Copy-paste evolution of wrapper metadata; defaults merged with overrides producing both keys.","solutions":["Keep 'executable' and delete 'content' if you want a generated wrapper","Keep 'content' and delete 'executable' if the launcher is fully hand-written"],"exampleFix":"# before\n{\"command_wrapper\": [\"tool\", {\"content\": \"#!/bin/bash\\n...\", \"executable\": \"bin/tool\"}]}\n# after\n{\"command_wrapper\": [\"tool\", {\"executable\": \"bin/tool\"}]}","handlingStrategy":"validation","validationCode":"if opts.get(\"content\").is_some() && opts.get(\"executable\").is_some() {\n    // reject before install: pick one\n}","typeGuard":"fn wrapper_sets_exactly_one(opts: &serde_json::Map<String, Value>) -> bool {\n    opts.get(\"content\").is_some() ^ opts.get(\"executable\").is_some()\n}","tryCatchPattern":null,"preventionTips":["When migrating between content and executable styles, delete the old key","Avoid merging wrapper option maps blindly; dedupe content/executable first"],"tags":["rust","mise","brew-cask","command-wrapper","mutually-exclusive"],"backgroundTag":"mutually-exclusive-config-fields","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}