usestrix/strix · error · ValueError

Two workspace files target /workspace/{workspace_rel}: '{see

Error message

Two workspace files target /workspace/{workspace_rel}: '{seen[workspace_rel]}' and '{source}'

What it means

Raised by resolve_workspace_files() when two --workspace-file specs resolve to the same destination inside /workspace. The 'seen' dict maps each workspace-relative destination to its first source; a second spec targeting the same path is rejected because upload order would silently decide which file wins.

Source

Thrown at strix/interface/utils.py:1737

    ``/workspace``; it defaults to the file name. Raises ``ValueError`` with a
    user-facing message when a spec is unusable.
    """
    resolved: list[dict[str, str]] = []
    seen: dict[str, str] = {}
    for spec in specs or []:
        raw, sep, dest = spec.rpartition(":")
        source_text = raw if sep and dest.strip() else spec
        source = Path(source_text.strip()).expanduser()
        if not source.is_file():
            raise ValueError(f"'{source}' is not an existing file")
        try:
            with source.open("rb"):
                pass
        except OSError as error:
            raise ValueError(f"Cannot read '{source}': {error}") from error
        workspace_rel = _workspace_file_dest(spec, source)
        if workspace_rel in seen:
            raise ValueError(
                f"Two workspace files target /workspace/{workspace_rel}: "
                f"'{seen[workspace_rel]}' and '{source}'"
            )
        seen[workspace_rel] = str(source)
        resolved.append(
            {
                "source_path": str(source.resolve()),
                "workspace_path": f"/workspace/{workspace_rel}",
            }
        )
    return resolved


def read_workspace_files(workspace_files: list[dict[str, str]] | None) -> list[dict[str, Any]]:
    """Read resolved workspace files into engine ``extra_files`` entries."""
    entries: list[dict[str, Any]] = []
    for workspace_file in workspace_files or []:
        source = Path(workspace_file["source_path"])

View on GitHub (pinned to 8551339130)

Solutions

  1. Give each colliding file an explicit distinct destination: --workspace-file dir1/config.yaml:svc1/config.yaml --workspace-file dir2/config.yaml:svc2/config.yaml
  2. Rename one source file before the run so default basenames differ
  3. Deduplicate merged spec lists before invoking strix (see validationCode below)

Example fix

# before
strix --workspace-file dir1/config.yaml --workspace-file dir2/config.yaml -t ./   # both -> /workspace/config.yaml
# after
strix --workspace-file dir1/config.yaml:svc1/config.yaml --workspace-file dir2/config.yaml:svc2/config.yaml -t ./
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def dedupe_specs(specs: list[str]) -> list[str]:
    seen: dict[str, str] = {}
    for spec in specs:
        raw, sep, dest = spec.rpartition(":")
        key = dest.strip() if sep and dest.strip() else Path(spec).name
        if key in seen:
            raise ValueError(f"duplicate destination {key}: {seen[key]} vs {spec}")
        seen[key] = spec
    return specs

Try / catch

try:
    resolve_workspace_files(specs)
except ValueError as e:
    if 'Two workspace files target' in str(e):
        assign_explicit_destinations_and_retry()
    else:
        raise

Prevention

When it happens

Trigger: Passing two specs with the same explicit destination: --workspace-file a.conf:app.conf --workspace-file b.conf:app.conf. Also triggered implicitly when two different source files share a basename: --workspace-file dir1/config.yaml --workspace-file dir2/config.yaml — both default to /workspace/config.yaml.

Common situations: Injecting configs from multiple directories whose files have identical names (config.yaml, .env, Dockerfile); merging specs from multiple config sources (CLI flags + config file) that both add the same file; forgetting that omitting DEST uses the source basename, colliding across directories.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/4c76a4056a691f47. Report an issue: GitHub.