{"record":{"id":"df7d0c27a69281e6","repo":"ansible/ansible","slug":"argument-spec-entry-contains-an-invalid-key-0","errorCode":null,"errorMessage":"argument spec entry contains an invalid key '{0}', valid keys: {1}","messagePattern":"argument spec entry contains an invalid key '(.+?)', valid keys: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"lib/ansible/module_utils/csharp/Ansible.Basic.cs","lineNumber":720,"sourceCode":"            NTAccount account = new NTAccount(stringValue);\n            return (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));\n        }\n\n        public static string ParseStr(object value) { return value.ToString(); }\n\n        private void ValidateArgumentSpec(IDictionary argumentSpec)\n        {\n            Dictionary<string, object> changedValues = new Dictionary<string, object>();\n            foreach (DictionaryEntry entry in argumentSpec)\n            {\n                string key = (string)entry.Key;\n\n                // validate the key is a valid argument spec key\n                if (!specDefaults.ContainsKey(key))\n                {\n                    string msg = String.Format(\"argument spec entry contains an invalid key '{0}', valid keys: {1}\",\n                        key, String.Join(\", \", specDefaults.Keys));\n                    throw new ArgumentException(FormatOptionsContext(msg, \" - \"));\n                }\n\n                // ensure the value is casted to the type we expect\n                Type optionType = null;\n                if (entry.Value != null)\n                    optionType = (Type)specDefaults[key][1];\n                if (optionType != null)\n                {\n                    Type actualType = entry.Value.GetType();\n                    bool invalid = false;\n                    if (optionType.IsGenericType && optionType.GetGenericTypeDefinition() == typeof(List<>))\n                    {\n                        // verify the actual type is not just a single value of the list type\n                        Type entryType = optionType.GetGenericArguments()[0];\n                        object[] arrayElementTypes = new object[]\n                        {\n                            null,  // ArrayList does not have an ElementType\n                            entryType,","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/module_utils/csharp/Ansible.Basic.cs#L702-L738","documentation":"Raised by git's set_git_dir/worktree handling when separating the .git directory from a worktree: shutil.move of the repo dir into place plus writing the 'gitdir: ' pointer file raised OSError. The code attempts rollback (moving the dir back) and chains the original OSError behind a generic Exception.","triggerScenarios":"Cloning with separate_git_dir: /path while a leftover directory already exists at the target of the move, the destination filesystem is read-only/full, or the worktree dir is not writable. The rollback itself can also fail, leaving partial state.","commonSituations":"Re-running a failed separate_git_dir task where /path/.git or the target repo dir already exists; NFS or container volumes refusing renames across filesystems; insufficient privileges on the clone destination.","solutions":["Inspect and clean both locations on the target: the worktree .git pointer and the separate_git_dir path; remove partial leftovers","Ensure the separate_git_dir destination is on a writable filesystem with space and is not already a populated dir","Re-run the task after cleanup — the clone is re-attempted from scratch"],"exampleFix":"# before\n- ansible.builtin.git:\n    repo: https://example.com/r.git\n    dest: /srv/work\n    separate_git_dir: /srv/gitstore/r.git\n# after (clean partial state first)\n- ansible.builtin.file:\n    path: '{{ item }}'\n    state: absent\n  loop: [/srv/work, /srv/gitstore/r.git]\n- ansible.builtin.git:\n    repo: https://example.com/r.git\n    dest: /srv/work\n    separate_git_dir: /srv/gitstore/r.git","handlingStrategy":"try-catch","validationCode":"import os\nif os.path.exists(separate_git_dir) and os.listdir(separate_git_dir):\n    raise RuntimeError(f'{separate_git_dir} already populated; clean before separate_git_dir clone')","typeGuard":null,"tryCatchPattern":"try:\n    set_git_dir(dest, repo_dir, worktree_dir)\nexcept Exception as e:\n    module.fail_json(msg=str(e), cause=repr(e.__cause__))","preventionTips":["Clean dest and separate_git_dir paths before re-running failed worktree clones","Keep the separate git dir on the same filesystem as the worktree to avoid cross-device renames"],"tags":["ansible","git","worktree","filesystem"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}