{"record":{"id":"4a9755dfdc7e504d","repo":"ansible/ansible","slug":"stdin-was-empty-not-encrypting","errorCode":null,"errorMessage":"stdin was empty, not encrypting","messagePattern":"stdin was empty, not encrypting","errorType":"exception","errorClass":"AnsibleOptionsError","httpStatus":null,"severity":"error","filePath":"lib/ansible/cli/vault.py","lineNumber":335,"sourceCode":"            else:\n                msg = \"String to encrypt:\"\n\n            prompt_response = display.prompt(msg, private=hide_input)\n\n            if prompt_response == '':\n                raise AnsibleOptionsError('The plaintext provided from the prompt was empty, not encrypting')\n\n            b_plaintext = to_bytes(prompt_response)\n            b_plaintext_list.append((b_plaintext, self.FROM_PROMPT, name))\n\n        # read from stdin\n        if self.encrypt_string_read_stdin:\n            if sys.stdout.isatty():\n                display.display(\"Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline)\", stderr=True)\n\n            stdin_text = sys.stdin.read()\n            if stdin_text == '':\n                raise AnsibleOptionsError('stdin was empty, not encrypting')\n\n            if sys.stdout.isatty() and not stdin_text.endswith(\"\\n\"):\n                display.display(\"\\n\")\n\n            b_plaintext = to_bytes(stdin_text)\n\n            # defaults to None\n            name = context.CLIARGS['encrypt_string_stdin_name']\n            b_plaintext_list.append((b_plaintext, self.FROM_STDIN, name))\n\n        # use any leftover args as strings to encrypt\n        # Try to match args up to --name options\n        if context.CLIARGS.get('encrypt_string_names', False):\n            name_and_text_list = list(zip(context.CLIARGS['encrypt_string_names'], args))\n\n            # Some but not enough --name's to name each var\n            if len(args) > len(name_and_text_list):\n                # Trying to avoid ever showing the plaintext in the output, so this warning is vague to avoid that.","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/cli/vault.py#L317-L353","documentation":"AnsibleOptionsError raised by the stdin-reading branch of encrypt_string (active when '-' is an arg, --encrypt-string-stdin-name is set, or no args/--name given) when sys.stdin.read() returns ''. Like the empty-prompt case, encrypting zero bytes from a declared stdin source is rejected rather than emitting an empty encrypted string.","triggerScenarios":"`echo -n '' | ansible-vault encrypt_string --stdin-name myvar`, redirecting an empty file (`ansible-vault encrypt_string - < /dev/null`), or a pipeline upstream that produced no output.","commonSituations":"CI jobs where the secret variable is unset so the pipe carries an empty string; a previous command in the pipeline failed silently and emitted nothing.","solutions":["Ensure the pipeline actually produces content: check the upstream command's output first","Guard in scripts: test -n \"$SECRET\" && printf '%s' \"$SECRET\" | ansible-vault encrypt_string --stdin-name myvar","If the value can legitimately be empty, decide explicitly — ansible-vault will not encrypt '' and you should skip the call"],"exampleFix":"# before\nprintf '%s' \"$MY_TOKEN\" | ansible-vault encrypt_string --stdin-name token  # MY_TOKEN unset\n\n# after\ntest -n \"$MY_TOKEN\" || { echo 'MY_TOKEN is empty' >&2; exit 1; }\nprintf '%s' \"$MY_TOKEN\" | ansible-vault encrypt_string --stdin-name token","handlingStrategy":"validation","validationCode":"import sys\n\ndata = sys.stdin.read()\nif data == '':\n    raise SystemExit('stdin empty; upstream producer failed or secret unset')\n# only then pipe into: ansible-vault encrypt_string --stdin-name NAME","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In pipelines, assert the secret variable is non-empty before piping","Fail loudly when a secrets-manager lookup returns '' instead of piping it onward"],"tags":["ansible","vault","cli","stdin","validation"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}