poetry
poetry copied to clipboard
Error: Unable to store the password for poetry-repository-pypi in the key ring: Failed to unlock the collection!
Hi, I am getting [KeyRingError] Unable to store the password for poetry-repository-pypi in the key ring: Failed to unlock the collection!
when running:
poetry config pypi-token.pypi <MY PYPI TOKEN>
Searched for this error everywhere but couldn't find anything. Running on the last version of Poetry and Ubuntu 18.04 LTS.
Also, if I set the token using an environment variable I get: Unable to retrieve the password for poetry-repository-pypi from the key ring
.
Can you try unlocking the collection using something like Seahorse?
Usually this happens when your keyring was left locked after login etc. Manual unlocks and/or reboots are known fix this issue. Note that this has nothing to do with poetry
or how it interacts with the OS keyring.
Why does poetry need the keyring? Is it possible to build/deploy in CI/CD without using a keyring?
@earonesty poetry
uses keyring
for storing credentials. It is entirely possible to build/deploy in CI/CD without any issues.
https://github.com/python-poetry/poetry/blob/17b165bf8c8d989d672417fd4610721df59ae1d0/.github/workflows/release.yml#L261-L266
@python-poetry/triage we should consider providing a error solution exception via crashtest or implement an option to skip keyring on failure when writing l; and warn in both write and read cases where this fails.
I have this problem with keyring working with Seahorse or something if I'm logged into a remote machine over ssh. If I log in with X2Go instead of getting an error it just freezes... 🤷🏼♂️ Will return with more info if I get any.
EDIT 1: I get this error "Failed to unlock the collection!" if I try to use keyring in the following manner while logged into a remote machine (Linux Mint 20 XFCE, Seahorse is the password manager):
import keyring
keyring.set_password("poetry-repository-testpypi", "__token__", "<my-testpypi-key>"
So I guess keyring doesn't work over SSH? I'll look into the issues over at jaraco/keyring.
EDIT 2: The README at jaraco/keyring provides instructions for running keyring on a headless system. This seems like quite a bit of hassle and very non-obvious for poetry users.
this fixed it for me... https://blog.frank-mich.com/python-poetry-1-0-0-private-repo-issue-fix/
@earonesty
poetry
useskeyring
for storing credentials. It is entirely possible to build/deploy in CI/CD without any issues.
right, but why bother storing credentials? i don't want it to.
- tried setting
POETRY_PYPI_TOKEN_PYPI
to a valid token... didn't help... still wants my keyring - seems like it should try reading from
~/.pypirc
like twine does... -
poetry config
and its sundry ways could be mentioned in the error messages? - tried the config - was "unable to unlock the collection" & how to turn off keyring support, so it will fall back?
- messed with dbus env vars... poetry decided to store stuff plain text.... which worked! but when i log in again, it goes back to failing to use the keyring unless i kill my dbus settings again
- sticking it on the command line works, but then i have to worry about my bash log
well, maybe a permission problem, with "sudo" save me in this case
Poetry strikes again 💣
Similar error occured when I was using poetry build
then poetry publish
to publish my python project to PYPI.🤔
But yesterday before the problem ocurred Poetry did in normal.
KeyRingError
Unable to retrieve the password for poetry-repository-pypi from the key ring
at ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/utils/password_manager.py:39 in get_password 35│ 36│ try: 37│ return keyring.get_password(name, username) 38│ except (RuntimeError, keyring.errors.KeyringError): → 39│ raise KeyRingError( 40│ "Unable to retrieve the password for {} from the key ring".format(name) 41│ ) 42│ 43│ def set_password(self, name, username, password):
Oh fixed it today by using poetry config http-basic.pypi username password
.
sudo pacman -S gnome-keyring
solved it for me.
sudo pacman -S gnome-keyring
This, but is not cool to have to install something of gnome
if you are not using gnome
...
Had the same problem in a container, solved it by setting the null keyring within the underlying lib, it's just an env variable:
PYTHON_KEYRING_BACKEND: keyring.backends.null.Keyring
see https://pypi.org/project/keyring/ disabling keyring
OK keyringerror again. Then fixed it by keyring --disable
in terminal on Ubuntu. Then poetry publish --build
as usual OK!
Why does poetry need the keyring? Is it possible to build/deploy in CI/CD without using a keyring?
I'm quite curious about this as well actually.
https://github.com/python-poetry/poetry/issues/2692#issuecomment-996489094
I can't remember ever having to install any package with root permissions. Infact, If I remember correctly, pip specifically warns against it.
Also, why exactly does poetry modify the error Traceback?
sigh I have other questions, but mainly why does poetry even request access from the keyring in the first place?
Installing keyrings.alt
fixed this for me. The problem was that only keyrings.google-artifactregistry-auth
was available, which does not have a set_password
this works to evade the keyring, and is appropriate for ci/cd
POETRY_HTTP_BASIC_TEST_USERNAME=__token__
POETRY_HTTP_BASIC_TEST_PASSWORD=pypi-secret
I'm running into a similar error with Poetry v1.2.0 for simple operations like installing a plugin in my Debian development environment. I'm not sure whether this is exactly the same issue as described above or just results in a similar error message.
$ poetry self add poetry-dynamic-versioning-plugin
Failed to unlock the collection!
This seems to have happened because I was SSH'd into my development environment, which has the GNOME Keyring installed. When I RDP'd in so I would have an X session, then the GNOME keyring dialog popped up to unlock the keyring. On the surface, it doesn't seem like there's any need for the keyring in this situation, because I'm installing a public plugin. It seems like maybe there's a code path where Poetry attempts to unlock the keyring even if it's not going to be needed.
I don't get this error on Windows or MacOS, although it's possible that a keyring is just silently being unlocked under the covers on those platforms, and I don't notice because it's not failing.
My workaround is to explicitly set a null keyring as suggested in @Cardu 's comment above, in Poetry issue #6277, and also in pip issue #6773:
$ PYTHON_KEYRING_BACKEND="keyring.backends.null.Keyring" poetry self add poetry-dynamic-versioning-plugin
I also confirmed that keyring --disable
works as in @KafCoppelia 's suggestion. However, I don't like that solution for my use case, because it permanently disables the keyring in configuration, and I do need the keyring available for other things.
Im also getting this error on my Debian Distro when trying to configure a new project with poetry init. When trying to specify the dependencies it fails with the following errors:
Package to add or search for (leave blank to skip): pydrive
[urllib3.connectionpool] Starting new HTTPS connection (1): pypi.org:443
[urllib3.connectionpool] https://pypi.org:443 "GET /search?q=pydrive HTTP/1.1" 301 215
[urllib3.connectionpool] https://pypi.org:443 "GET /search/?q=pydrive HTTP/1.1" 200 23369
Found 20 packages matching pydrive
Showing the first 10 matches
Enter package # to add, or the complete package name if it is not listed []:
[ 0] PyDrive
[ 1] PyDrive3
[ 2] PyDrive2
[ 3] pydriver
[ 4] pydriveziead
[ 5] pydrivedol
[ 6] drivelib
[ 7] GsuiteToMd
[ 8] yagdrive
[ 9] free-storage
[10]
> 0
Enter the version constraint to require (or leave blank to use the latest version):
[keyring.backend] Loading KWallet
[keyring.backend] Loading SecretService
[keyring.backend] Loading Windows
[keyring.backend] Loading chainer
[keyring.backend] Loading libsecret
[keyring.backend] Loading macOS
Stack trace:
29 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cleo/application.py:329 in run
327│
328│ try:
→ 329│ exit_code = self._run(io)
330│ except Exception as e:
331│ if not self._catch_exceptions:
28 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/console/application.py:185 in _run
183│ self._load_plugins(io)
184│
→ 185│ exit_code: int = super()._run(io)
186│ return exit_code
187│
27 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cleo/application.py:423 in _run
421│ io.input.set_stream(stream)
422│
→ 423│ exit_code = self._run_command(command, io)
424│ self._running_command = None
425│
26 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cleo/application.py:465 in _run_command
463│
464│ if error is not None:
→ 465│ raise error
466│
467│ return event.exit_code
25 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cleo/application.py:449 in _run_command
447│
448│ if event.command_should_run():
→ 449│ exit_code = command.run(io)
450│ else:
451│ exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED
24 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cleo/commands/base_command.py:119 in run
117│ io.input.validate()
118│
→ 119│ status_code = self.execute(io)
120│
121│ if status_code is None:
23 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cleo/commands/command.py:83 in execute
81│
82│ try:
→ 83│ return self.handle()
84│ except KeyboardInterrupt:
85│ return 1
22 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/console/commands/init.py:188 in handle
186│ help_displayed = True
187│ requirements.update(
→ 188│ self._format_requirements(self._determine_requirements([]))
189│ )
190│ if self.io.is_interactive():
21 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/console/commands/init.py:338 in _determine_requirements
336│ if package_constraint is None:
337│ _, package_constraint = self._find_best_version_for_package(
→ 338│ package
339│ )
340│
20 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/console/commands/init.py:399 in _find_best_version_for_package
397│ selector = VersionSelector(self._get_pool())
398│ package = selector.find_best_candidate(
→ 399│ name, required_version, allow_prereleases=allow_prereleases, source=source
400│ )
401│
19 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/version/version_selector.py:39 in find_best_candidate
37│ },
38│ )
→ 39│ candidates = self._pool.find_packages(dependency)
40│ only_prereleases = all(c.version.is_unstable() for c in candidates)
41│
18 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/pool.py:181 in find_packages
179│ packages = []
180│ for repo in self._repositories:
→ 181│ packages += repo.find_packages(dependency)
182│
183│ return packages
17 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/repository.py:46 in find_packages
44│ ignored_pre_release_packages = []
45│
→ 46│ for package in self._find_packages(dependency.name, constraint):
47│ if package.yanked and not isinstance(constraint, Version):
48│ # PEP 592: yanked files are always ignored, unless they are the only
16 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/pypi_repository.py:116 in _find_packages
114│ """
115│ try:
→ 116│ info = self.get_package_info(name)
117│ except PackageNotFound:
118│ self._log(
15 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/pypi_repository.py:105 in get_package_info
103│
104│ package_info: dict[str, Any] = self._cache.store("packages").remember_forever(
→ 105│ name, lambda: self._get_package_info(name)
106│ )
107│ return package_info
14 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cachy/repository.py:174 in remember_forever
172│ return val
173│
→ 174│ val = value(callback)
175│
176│ self.forever(key, val)
13 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/cachy/helpers.py:6 in value
4│ def value(val):
5│ if callable(val):
→ 6│ return val()
7│
8│ return val
12 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/pypi_repository.py:105 in <lambda>
103│
104│ package_info: dict[str, Any] = self._cache.store("packages").remember_forever(
→ 105│ name, lambda: self._get_package_info(name)
106│ )
107│ return package_info
11 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/pypi_repository.py:155 in _get_package_info
153│
154│ def _get_package_info(self, name: NormalizedName) -> dict[str, Any]:
→ 155│ data = self._get(f"pypi/{name}/json")
156│ if data is None:
157│ raise PackageNotFound(f"Package [{name}] not found.")
10 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/repositories/pypi_repository.py:244 in _get
242│ self._base_url + endpoint,
243│ raise_for_status=False,
→ 244│ timeout=REQUESTS_TIMEOUT,
245│ )
246│ except requests.exceptions.TooManyRedirects:
9 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/authenticator.py:246 in get
244│
245│ def get(self, url: str, **kwargs: Any) -> requests.Response:
→ 246│ return self.request("get", url, **kwargs)
247│
248│ def post(self, url: str, **kwargs: Any) -> requests.Response:
8 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/authenticator.py:187 in request
185│ ) -> requests.Response:
186│ request = requests.Request(method, url)
→ 187│ credential = self.get_credentials_for_url(url)
188│
189│ if credential.username is not None or credential.password is not None:
7 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/authenticator.py:310 in get_credentials_for_url
308│ # no credentials were provided in the url, try finding the
309│ # best repository configuration
→ 310│ self._credentials[url] = self._get_credentials_for_url(url)
311│ else:
312│ # Split from the right because that's how urllib.parse.urlsplit()
6 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/authenticator.py:272 in _get_credentials_for_url
270│ credential = (
271│ self._get_credentials_for_repository(repository=repository)
→ 272│ if repository is not None
273│ else HTTPAuthCredential()
274│ )
5 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/authenticator.py:260 in _get_credentials_for_repository
258│ if key not in self._credentials:
259│ self._credentials[key] = repository.get_http_credentials(
→ 260│ password_manager=self._password_manager, username=username
261│ )
262│
4 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/authenticator.py:91 in get_http_credentials
89│ # fallback to url and netloc based keyring entries
90│ credential = password_manager.keyring.get_credential(
→ 91│ self.url, self.netloc, username=credential.username
92│ )
93│
3 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/poetry/utils/password_manager.py:51 in get_credential
49│
50│ for name in names:
→ 51│ credential = keyring.get_credential(name, username)
52│ if credential:
53│ return HTTPAuthCredential(
2 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/keyring/core.py:72 in get_credential
70│ ) -> typing.Optional[credentials.Credential]:
71│ """Get a Credential for the specified service."""
→ 72│ return get_keyring().get_credential(service_name, username)
73│
74│
1 ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/keyring/backends/SecretService.py:112 in get_credential
110│ scheme = self.schemes[self.scheme]
111│ query = self._query(service, username)
→ 112│ collection = self.get_preferred_collection()
113│
114│ with closing(collection.connection):
KeyringLocked
Failed to unlock the collection!
at ~/.local/share/pypoetry/venv/lib/python3.7/site-packages/keyring/backends/SecretService.py:67 in get_preferred_collection
63│ raise InitError("Failed to create the collection: %s." % e)
64│ if collection.is_locked():
65│ collection.unlock()
66│ if collection.is_locked(): # User dismissed the prompt
→ 67│ raise KeyringLocked("Failed to unlock the collection!")
68│ return collection
69│
70│ def unlock(self, item):
71│ if hasattr(item, 'unlock'):
Also happens to me when connecting via SSH, and my workaround is to disable keyring
within a sufficient scope, as poetry
can work without keyring
.
My two cents are that this behaviour is not consistent with the docs.
The documentation promises a backup in case of keyring
failure:
If a system keyring is available and supported, the password is stored to and retrieved from the keyring...
If access to keyring fails or is unsupported, this will **fall back to writing the password to the auth.toml** file along with the username.
Of course, it may well be an issue on the keyring side (locked, not set up properly...), but would be nice to fall back gracefully. A bit odd, but sometimes poetry depends on keyring
even for password-free operations in config:
(.venv) azureuser@sense-mskorski:~/projects/test_project$ poetry config virtualenvs.create false
KeyRingError
Unable to retrieve the password for poetry-repository-my_private_repo from the key ring
EDIT: the keyring usage is handled in poetry.utils.password_manager
and has improved a bit since in version 1.2
, in particular with respect to null backends.
https://github.com/python-poetry/poetry/blob/0686427ce175e14b69c8ffeca4515cce79453047/src/poetry/utils/password_manager.py#L109-L141
Closing as duplicate of #1917
Had the same problem in a container, solved it by setting the null keyring within the underlying lib, it's just an env variable:
PYTHON_KEYRING_BACKEND: keyring.backends.null.Keyring
see https://pypi.org/project/keyring/ disabling keyring
This, easiest solution and worked perfectly
I ran into same issue after updating Poetry from 1.1.xxx to 1.2.2 on Mac BigSur. Before the update it was fine, but after Poetry couldn't read keychain file I advise you not to disable keyring and store password in auth.toml as it is stored plaintext! What helped me was to allow read Poetry's keychain file by any application and then return to ask for access and add python to allowed apps again. Hope this helps you and saves you some time
I have a Mac, and I needed to delete an old password in the Keychain in order to get it to work. I went to the Keychain Access
app, navigated to the login
default keychain and filtered on Passwords
. In there was one called poetry-repositor-***
, where ***
was my private repo. Deleting that and running poetry config http-basic.<PRIVATE-REPO> <USER> <TOKEN>
again solved this issue for me.
Just to add to the macos solutions above: the Issue for me was that the key is added to the keychain with access only allowed by a specific python version. When I switched python versions then the poetry config command started failing. The solution is to allow all apps on the poetry keys or add the additional python versions you need. Ideally poetry would handle this or at least provide a better error message.
fwiw, i found this really helpful for getting into my keyring on a remote box (jammy/ubuntu) with gnome-keyring
installed: https://unix.stackexchange.com/a/602935
note that you have to source
the file every time to get it to run correctly.
[MacOS]
I have the same keyring issue with poetry
installed with pip
.
Un-installing poetry
with pip
and re-install it with brew
this time solved the issue on my side.
On macOs:
python -m keyring --disable
and
poetry config pypi-token.pypi <MY PYPI TOKEN>
worked for me.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.