dvc: push: Infinite loop in credential configuration detected
Bug Report
Description
I am using dvc with an AWS S3 remote. The credentials to access to S3 are handled by aws-vault.
When using dvc 2.5.4, everything works fine. However, with 2.6.x or newer, I get the following error when I try to dvc push
:
ERROR: unexpected error - Infinite loop in credential configuration detected. Attempting to load from profile my-profile-a which has already been visited. Visited profiles: ['my-profile-b', 'my-profile-a']
The error appears if:
- I try to
dvc push
after having updated a file inside a dvc-tracked folder.
However, I can dvc push
normally if:
- I add a new file to a dvc-tracked folder.
- I add a new dvc-tracked file.
- I update a dvc-tracked file.
My aws-vault
credentials configuration is as follows:
[profile my-profile-a]
region=eu-west-3
s3.multipart_threshold = 5GB
credential_process=aws-vault exec --no-session --json my-profile-a
s3=
multipart_threshold = 5GB
[profile my-profile-b]
region=us-west-1
source_profile = my-profile-a
role_arn = arn:aws:iam::123456789012:role/MyRole
role_session_name = my.name
s3=
multipart_threshold = 5GB
The dvc
config is as follows:
[core]
remote = s3remote
['remote "s3remote"']
url = s3://my-bucket
profile = my-profile-b
A possible explanation is that dvc
calls the botocore function that checks the credentials more than once. At first I thought it to be related to this botocore issue but as the error appears only when trying to dvc push
a folder after an update to one of its files, the issue seems to be related to dvc.
Reproduce
- Set aws-vault with a similar configuration
- Set dvc with a similar configuration
- Add and push a folder to dvc
- Update an existing file inside this folder
- Try to
dvc push
the folder
Expected
dvc push
should be possible.
Environment information
Output of dvc doctor
:
$ dvc doctor
DVC version: 3.30.1 (pip)
-------------------------
Platform: Python 3.10.10 on Linux-5.15.0-89-generic-x86_64-with-glibc2.31
Subprojects:
dvc_data = 2.22.0
dvc_objects = 1.2.0
dvc_render = 0.6.0
dvc_task = 0.3.0
scmrepo = 1.5.0
Supports:
http (aiohttp = 3.9.0, aiohttp-retry = 2.8.3),
https (aiohttp = 3.9.0, aiohttp-retry = 2.8.3),
s3 (s3fs = 2023.10.0, boto3 = 1.28.64)
Config:
Global: /home/myname/.config/dvc
System: /etc/xdg/xdg-ubuntu/dvc
Cache types: hardlink, symlink
Cache directory: ext4 on /dev/mapper/vgubuntu-root
Caches: local
Remotes: s3
Workspace directory: ext4 on /dev/mapper/vgubuntu-root
Repo: dvc, git
Repo.site_cache_dir: /var/tmp/dvc/repo/8767037a1b741787f352cb10a11ee443
Additional Information (if any):
$ dvc push -v
2023-12-07 16:52:31,294 DEBUG: v3.30.1 (pip), CPython 3.10.10 on Linux-5.15.0-89-generic-x86_64-with-glibc2.31
2023-12-07 16:52:31,294 DEBUG: command: /home/myname/work/tmp/test-dvc-versions/.venv/bin/dvc push -v
2023-12-07 16:52:31,618 DEBUG: Preparing to transfer data from '/home/myname/work/tmp/test-dvc-versions/.dvc/cache/files/md5' to 's3://my-bucket/myname/test-dvc-versions/files/md5'
2023-12-07 16:52:31,619 DEBUG: Preparing to collect status from 'my-bucket/myname/test-dvc-versions/files/md5'
2023-12-07 16:52:31,619 DEBUG: Collecting status from 'my-bucket/myname/test-dvc-versions/files/md5'
2023-12-07 16:52:31,622 DEBUG: Querying 2 oids via object_exists
2023-12-07 16:52:33,528 ERROR: unexpected error - Infinite loop in credential configuration detected. Attempting to load from profile my-profile-a which has already been visited. Visited profiles: ['my-profile-b', 'my-profile-a']
Traceback (most recent call last):
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc/cli/__init__.py", line 211, in main
ret = cmd.do_run()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc/cli/command.py", line 27, in do_run
return self.run()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc/commands/data_sync.py", line 64, in run
processed_files_count = self.repo.push(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc/repo/__init__.py", line 60, in wrapper
return f(repo, *args, **kwargs)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc/repo/push.py", line 117, in push
push_transferred, push_failed = ipush(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_data/index/push.py", line 68, in push
result = transfer(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_data/hashfile/transfer.py", line 204, in transfer
status = compare_status(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_data/hashfile/status.py", line 176, in compare_status
dest_exists, dest_missing = status(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_data/hashfile/status.py", line 136, in status
exists = hashes.intersection(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_data/hashfile/status.py", line 45, in _indexed_dir_hashes
indexed_dir_exists.update(hashes)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/tqdm/std.py", line 1182, in __iter__
for obj in iterable:
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_objects/db.py", line 359, in list_oids_exists
in_remote = self.fs.exists(paths, batch_size=jobs)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_objects/fs/base.py", line 371, in exists
return fut.result()
File "/home/myname/.pyenv/versions/3.10.10/lib/python3.10/concurrent/futures/_base.py", line 458, in result
return self.__get_result()
File "/home/myname/.pyenv/versions/3.10.10/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/dvc_objects/executors.py", line 134, in batch_coros
result = fut.result()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/s3fs/core.py", line 1035, in _exists
await self._info(path, bucket, key, version_id=version_id)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/s3fs/core.py", line 1302, in _info
out = await self._call_s3(
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/s3fs/core.py", line 341, in _call_s3
await self.set_session()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/s3fs/core.py", line 522, in set_session
self._s3 = await s3creator.get_client()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/s3fs/utils.py", line 72, in get_client
self._client = await self._stack.enter_async_context(
File "/home/myname/.pyenv/versions/3.10.10/lib/python3.10/contextlib.py", line 619, in enter_async_context
result = await _cm_type.__aenter__(cm)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/aiobotocore/session.py", line 27, in __aenter__
self._client = await self._coro
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/aiobotocore/session.py", line 173, in _create_client
credentials = await self.get_credentials()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/aiobotocore/session.py", line 83, in get_credentials
self._credentials = await (
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/aiobotocore/credentials.py", line 960, in load_credentials
creds = await provider.load()
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/aiobotocore/credentials.py", line 689, in load
return await self._load_creds_via_assume_role(self._profile_name)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/aiobotocore/credentials.py", line 692, in _load_creds_via_assume_role
role_config = self._get_role_config(profile_name)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/botocore/credentials.py", line 1562, in _get_role_config
self._validate_source_profile(profile_name, source_profile)
File "/home/myname/work/tmp/test-dvc-versions/.venv/lib/python3.10/site-packages/botocore/credentials.py", line 1613, in _validate_source_profile
raise InfiniteLoopConfigError(
botocore.exceptions.InfiniteLoopConfigError: Infinite loop in credential configuration detected. Attempting to load from profile my-profile-a which has already been visited. Visited profiles: ['my-profile-b', 'my-profile-a']
2023-12-07 16:52:33,621 DEBUG: link type reflink is not available ([Errno 95] no more link types left to try out)
2023-12-07 16:52:33,622 DEBUG: Removing '/home/myname/work/tmp/.iKooz7Cn9gqk4S6XK6HrH2.tmp'
2023-12-07 16:52:33,622 DEBUG: Removing '/home/myname/work/tmp/.iKooz7Cn9gqk4S6XK6HrH2.tmp'
2023-12-07 16:52:33,623 DEBUG: Removing '/home/myname/work/tmp/.iKooz7Cn9gqk4S6XK6HrH2.tmp'
2023-12-07 16:52:33,624 DEBUG: Removing '/home/myname/work/tmp/test-dvc-versions/.dvc/cache/files/md5/.R58Taoujw2rofT9vbPZxxm.tmp'
2023-12-07 16:52:33,646 DEBUG: Version info for developers:
DVC version: 3.30.1 (pip)
-------------------------
Platform: Python 3.10.10 on Linux-5.15.0-89-generic-x86_64-with-glibc2.31
Subprojects:
dvc_data = 2.22.0
dvc_objects = 1.2.0
dvc_render = 0.6.0
dvc_task = 0.3.0
scmrepo = 1.5.0
Supports:
http (aiohttp = 3.9.0, aiohttp-retry = 2.8.3),
https (aiohttp = 3.9.0, aiohttp-retry = 2.8.3),
s3 (s3fs = 2023.10.0, boto3 = 1.28.64)
Config:
Global: /home/myname/.config/dvc
System: /etc/xdg/xdg-ubuntu/dvc
Cache types: hardlink, symlink
Cache directory: ext4 on /dev/mapper/vgubuntu-root
Caches: local
Remotes: s3
Workspace directory: ext4 on /dev/mapper/vgubuntu-root
Repo: dvc, git
Repo.site_cache_dir: /var/tmp/dvc/repo/8767037a1b741787f352cb10a11ee443
Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!
2023-12-07 16:52:33,649 DEBUG: Analytics is enabled.
2023-12-07 16:52:33,716 DEBUG: Trying to spawn ['daemon', 'analytics', '/tmp/tmpfw6iwkr3', '-v']
2023-12-07 16:52:33,722 DEBUG: Spawned ['daemon', 'analytics', '/tmp/tmpfw6iwkr3', '-v'] with pid 29059
About this issue
- Original URL
- State: closed
- Created 7 months ago
- Comments: 17 (6 by maintainers)
Thanks a lot !
Yes it does !
@nisace Sorry, I still didn’t have time to look into this. But regarding pull, it is meant to catch errors and fetch whatever it can and then checkout whatever it can and
checkout
is where previously occured errors might show up as missing files. I’m not sure how this cold cause “infinite loop in credential” error though.@efiop, I’ve looked at it again and noticed that
dvc status -c
always hit the raise ofInfiniteLoopConfigError
at this line of botocore (both with or without a dvc cache). However, the expection is effectively raised (meaning thedvc status -c
command breaks) only when advc
cache is present. Thus it seems that the exception get caught somewhere. But I haven’t found where yet. Do you have any clue? Thanks !@efiop thanks for you response ! Yes, fresh push does not produce the error. I’ve tried again and here is the behavior:
dvc add
a new folder: okdvc push
the folder: okdvc add
: okdvc status
: ok (Data and pipelines are up to date
)dvc status -c
: ok, produces the following outputdvc push
the folder: okdvc push
again without any modification: the error appearsdvc status
: ok (Data and pipelines are up to date
)dvc status -c
: the error appearsThus, in fact, there is no need to update a file in the folder to make the error appear.