{"record":{"id":"14cb9646c65cd630","repo":"ansible/ansible","slug":"not-a-tty-editor-cannot-be-opened","errorCode":null,"errorMessage":"not a tty, editor cannot be opened","messagePattern":"not a tty, editor cannot be opened","errorType":"exception","errorClass":"AnsibleOptionsError","httpStatus":null,"severity":"error","filePath":"lib/ansible/cli/vault.py","lineNumber":457,"sourceCode":"            display.display(\"Reading ciphertext input from stdin\", stderr=True)\n\n        for f in context.CLIARGS['args'] or ['-']:\n            self.editor.decrypt_file(f, output_file=context.CLIARGS['output_file'])\n\n        if sys.stdout.isatty():\n            display.display(\"Decryption successful\", stderr=True)\n\n    def execute_create(self):\n        \"\"\" create and open a file in an editor that will be encrypted with the provided vault secret when closed\"\"\"\n\n        if len(context.CLIARGS['args']) != 1:\n            raise AnsibleOptionsError(\"ansible-vault create can take only one filename argument\")\n\n        if sys.stdout.isatty() or context.CLIARGS['skip_tty_check']:\n            self.editor.create_file(context.CLIARGS['args'][0], self.encrypt_secret,\n                                    vault_id=self.encrypt_vault_id)\n        else:\n            raise AnsibleOptionsError(\"not a tty, editor cannot be opened\")\n\n    def execute_edit(self):\n        \"\"\" open and decrypt an existing vaulted file in an editor, that will be encrypted again when closed\"\"\"\n        for f in context.CLIARGS['args']:\n            self.editor.edit_file(f)\n\n    def execute_view(self):\n        \"\"\" open, decrypt and view an existing vaulted file using a pager using the supplied vault secret \"\"\"\n\n        for f in context.CLIARGS['args']:\n            # Note: vault should return byte strings because it could encrypt\n            # and decrypt binary files.  We are responsible for changing it to\n            # unicode here because we are displaying it and therefore can make\n            # the decision that the display doesn't have to be precisely what\n            # the input was (leave that to decrypt instead)\n            plaintext = self.editor.plaintext(f)\n            self.pager(to_text(plaintext))\n","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/cli/vault.py#L439-L475","documentation":"AnsibleOptionsError raised by VaultCLI.execute_create when stdout is not a TTY and --skip-tty-check was not passed. `ansible-vault create` needs to spawn $EDITOR interactively; without a terminal the editor cannot run, so Ansible aborts instead of hanging or corrupting the file. (Note the check is on stdout being a tty, so piping output also triggers it.)","triggerScenarios":"Running `ansible-vault create f.yml` inside CI, cron, a non-interactive SSH session without -t, or with output piped/redirected, without --skip-tty-check.","commonSituations":"Automation/CI attempts to use `create`; docker exec without -t; nohup'd scripts. Also $EDITOR unset or nonfunctional in minimal environments.","solutions":["For automation, avoid create entirely: write the plaintext then `ansible-vault encrypt` it, or pipe to `ansible-vault encrypt_string --stdin-name`","If a real terminal exists upstream (e.g. ssh), allocate it: ssh -t, docker exec -it","As a last resort, --skip-tty-check lets it proceed, but the editor still needs to work non-interactively (e.g. EDITOR=true with content pre-supplied)"],"exampleFix":"# before (CI job)\nansible-vault create secret.yml  # fails: not a tty\n\n# after\nprintf 'my_secret: value\\n' > secret.yml\nansible-vault encrypt --vault-id prompt secret.yml","handlingStrategy":"validation","validationCode":"import sys, os\n\ndef create_is_safe() -> bool:\n    return sys.stdout.isatty() or bool(os.environ.get('ANSIBLE_VAULT_SKIP_TTY_CHECK'))\n\nif not create_is_safe():\n    # non-interactive: write plaintext, then encrypt\n    pass","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use `ansible-vault create` in automation; write-then-encrypt instead","Allocate a TTY (ssh -t, docker exec -it) for interactive create sessions"],"tags":["ansible","vault","cli","tty","editor"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}