Calkit run crashes if no dvc remote set
- Dominant language
- Python
- Stars
- 60
- Forks
- 18
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 38
Description
I updated from calkit 25.2 to 26.8 and now `calkit run` causes an error. It seems to be because I don't have dvc set up (which is due to the error 403 I was having here https://github.com/calkit/calkit-assistant/issues/24).
`ConfigError: config file error: expected 'url' for dictionary value @ data['remote']['calkit']`
Full traceback
(wec-decider-decider-2) becca@cornell-MS-7B94:~/Documents/git/WEC-DECIDER$ calkit run
Getting system information
Checking system-level dependencies
Compiling DVC pipeline
WARNING: Process '/home/becca/.local/share/uv/tools/calkit-python/lib/python3.10/site-packages/dvc/__main__.py repro setup-sweep' with (Pid 2430793), in RWLock-file '.calkit/env-locks/decider.yml' had been killed. Auto removed it from the lock file.
╭─────────────────────────────────────────────────── Traceback (most recent call last) ────────────────────────────────────────────────────╮
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/calkit/cli/main.py:935 in run │
│ │
│ 932 │ # Get status of DVC repo before running │
│ 933 │ dvc_repo = dvc.repo.Repo() │
│ 934 │ dvc_status_before = dvc_repo.status() │
│ ❱ 935 │ dvc_data_status_before = dvc_repo.data_status() │
│ 936 │ dvc_data_status_before.pop("git", None) # Remove git status │
│ 937 │ if targets is None: │
│ 938 │ │ targets = [] │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/data.py:413 in status │
│ │
│ 410 │ │ ) │
│ 411 │ │
│ 412 │ try: │
│ ❱ 413 │ │ committed_diff = _diff_head_to_index( │
│ 414 │ │ │ repo, filter_keys=filter_keys, head=head, granular=granular │
│ 415 │ │ ) │
│ 416 │ except (SCMError, NoSCMError): │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/data.py:276 in _diff_head_to_index │
│ │
│ 273 │ │
│ 274 │ try: │
│ 275 │ │ with repo.switch(head): │
│ ❱ 276 │ │ │ head_index = repo.index.data["repo"] │
│ 277 │ │ │ head_view = filter_index(head_index, filter_keys=filter_keys) │
│ 278 │ except RevError: │
│ 279 │ │ logger.debug("failed to switch to '%s'", head) │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/funcy/objects.py:25 in __get__ │
│ │
│ 22 │ def __get__(self, instance, type=None): │
│ 23 │ │ if instance is None: │
│ 24 │ │ │ return self │
│ ❱ 25 │ │ res = instance.__dict__[self.fget.__name__] = self.fget(instance) │
│ 26 │ │ return res │
│ 27 │
│ 28 │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/__init__.py:290 in index │
│ │
│ 287 │ def index(self) -> "Index": │
│ 288 │ │ from dvc.repo.index import Index │
│ 289 │ │ │
│ ❱ 290 │ │ return Index.from_repo(self) │
│ 291 │ │
│ 292 │ def check_graph( │
│ 293 │ │ self, stages: Iterable["Stage"], callback: Optional[Callable] = None │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/index.py:330 in from_repo │
│ │
│ 327 │ │ datasets_lock = {} │
│ 328 │ │ │
│ 329 │ │ onerror = onerror or repo.stage_collection_error_handler │
│ ❱ 330 │ │ for _, idx in collect_files(repo, onerror=onerror): │
│ 331 │ │ │ stages.extend(idx.stages) │
│ 332 │ │ │ metrics.update(idx._metrics) │
│ 333 │ │ │ plots.update(idx._plots) │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/index.py:90 in collect_files │
│ │
│ 87 │ │ for file in filter(dvcfile_filter, files): │
│ 88 │ │ │ file_path = fs.join(root, file) │
│ 89 │ │ │ try: │
│ ❱ 90 │ │ │ │ index = Index.from_file(repo, file_path) │
│ 91 │ │ │ except DvcException as exc: │
│ 92 │ │ │ │ if onerror: │
│ 93 │ │ │ │ │ onerror(relpath(file_path), exc) │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/index.py:356 in from_file │
│ │
│ 353 │ │ dvcfile = load_file(repo, path) │
│ 354 │ │ return cls( │
│ 355 │ │ │ repo, │
│ ❱ 356 │ │ │ stages=list(dvcfile.stages.values()), │
│ 357 │ │ │ metrics={path: dvcfile.metrics} if dvcfile.metrics else {}, │
│ 358 │ │ │ plots={path: dvcfile.plots} if dvcfile.plots else {}, │
│ 359 │ │ │ params={path: dvcfile.params} if dvcfile.params else {}, │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/funcy/objects.py:25 in __get__ │
│ │
│ 22 │ def __get__(self, instance, type=None): │
│ 23 │ │ if instance is None: │
│ 24 │ │ │ return self │
│ ❱ 25 │ │ res = instance.__dict__[self.fget.__name__] = self.fget(instance) │
│ 26 │ │ return res │
│ 27 │
│ 28 │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/dvcfile.py:313 in stages │
│ │
│ 310 │ │
│ 311 │ @cached_property │
│ 312 │ def stages(self) -> LOADER: │
│ ❱ 313 │ │ return self.LOADER(self, self.contents, self.lockfile_contents) │
│ 314 │ │
│ 315 │ @property │
│ 316 │ def artifacts(self) -> dict[str, Optional[dict[str, Any]]]: │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/stage/loader.py:30 in __init__ │
│ │
│ 27 class StageLoader(Mapping): │
│ 28 │ def __init__(self, dvcfile: "ProjectFile", data, lockfile_data=None): │
│ 29 │ │ self.dvcfile = dvcfile │
│ ❱ 30 │ │ self.resolver = self.dvcfile.resolver │
│ 31 │ │ self.data = data or {} │
│ 32 │ │ self.stages_data = self.data.get("stages", {}) │
│ 33 │ │ self.repo = self.dvcfile.repo │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/funcy/objects.py:25 in __get__ │
│ │
│ 22 │ def __get__(self, instance, type=None): │
│ 23 │ │ if instance is None: │
│ 24 │ │ │ return self │
│ ❱ 25 │ │ res = instance.__dict__[self.fget.__name__] = self.fget(instance) │
│ 26 │ │ return res │
│ 27 │
│ 28 │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/dvcfile.py:309 in resolver │
│ │
│ 306 │ │ from .parsing import DataResolver │
│ 307 │ │ │
│ 308 │ │ wdir = self.repo.fs.parent(self.path) │
│ ❱ 309 │ │ return DataResolver(self.repo, wdir, self.contents) │
│ 310 │ │
│ 311 │ @cached_property │
│ 312 │ def stages(self) -> LOADER: │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/parsing/__init__.py:140 in __init__ │
│ │
│ 137 class DataResolver: │
│ 138 │ def __init__(self, repo: "Repo", wdir: str, d: dict): │
│ 139 │ │ self.fs = fs = repo.fs │
│ ❱ 140 │ │ self.parsing_config = repo.config.get("parsing", {}) │
│ 141 │ │ │
│ 142 │ │ if os.path.isabs(wdir): │
│ 143 │ │ │ wdir = fs.relpath(wdir) │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/funcy/objects.py:25 in __get__ │
│ │
│ 22 │ def __get__(self, instance, type=None): │
│ 23 │ │ if instance is None: │
│ 24 │ │ │ return self │
│ ❱ 25 │ │ res = instance.__dict__[self.fget.__name__] = self.fget(instance) │
│ 26 │ │ return res │
│ 27 │
│ 28 │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/repo/__init__.py:246 in config │
│ │
│ 243 │ def config(self): │
│ 244 │ │ from dvc.config import Config │
│ 245 │ │ │
│ ❱ 246 │ │ return Config( │
│ 247 │ │ │ self.dvc_dir, │
│ 248 │ │ │ local_dvc_dir=self.local_dvc_dir, │
│ 249 │ │ │ fs=self.fs, │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/config.py:117 in __init__ │
│ │
│ 114 │ │ if not fs and not local_dvc_dir: │
│ 115 │ │ │ self.local_dvc_dir = dvc_dir │
│ 116 │ │ │
│ ❱ 117 │ │ self.load( │
│ 118 │ │ │ validate=validate, config=config, remote=remote, remote_config=remote_config │
│ 119 │ │ ) │
│ 120 │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/config.py:193 in load │
│ │
│ 190 │ │ │ merge(conf, config) │
│ 191 │ │ │
│ 192 │ │ if validate: │
│ ❱ 193 │ │ │ conf = self.validate(conf) │
│ 194 │ │ │
│ 195 │ │ self.clear() │
│ 196 │
│ │
│ /home/becca/.local/share/uv/tools/calkit-python/lib/python3.12/site-packages/dvc/config.py:401 in validate │
│ │
│ 398 │ │ try: │
│ 399 │ │ │ return get_compiled_schema()(data) │
│ 400 │ │ except Invalid as exc: │
│ ❱ 401 │ │ │ raise ConfigError(str(exc)) from None │
│ 402 │
│ 403 │
│ 404 def _parse_named(conf): │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
ConfigError: config file error: expected 'url' for dictionary value @ data['remote']['calkit']
I was able to fix it by running `calkit config remote` which committed a .dvc/config file that I already had locally untracked.
```
(wec-decider-decider-2) becca@cornell-MS-7B94:~/Documents/git/WEC-DECIDER$ calkit config remote
Setting 'calkit' as a default remote.
Committing changes to DVC config
```
I have solved the issue for myself but still posting it here in case you want to update the code to prevent this error in the future.
Calkit 26.8, Ubuntu
Contributor guide
Assessment
This issue has not been assessed yet.