abhigyanpatwari/GitNexus · error · ValueError

--promotion-target-bases-json must contain a string mapping

Error message

--promotion-target-bases-json must contain a string mapping

What it means

Raised in main() when --promotion-target-bases-json is supplied but is not a dict whose every key and value are strings (a string→string mapping). The flag carries destination-base digests used by promotion, so a non-object or any non-string key/value is rejected. Caught with the other input errors and surfaced through parser.error (exit 2).

Source

Thrown at eval/workflow_bench/runner.py:936

        task_document = yaml.safe_load(args.tasks.read_text())
        if not isinstance(task_document, Mapping) or not isinstance(task_document.get("tasks"), list):
            raise ValueError("task file must contain a tasks list")
        tasks, skipped_expensive = select_tasks(
            task_document["tasks"],
            include_expensive=args.include_expensive,
        )
        oracle_snapshots = capture_task_oracles(tasks)
        expected_task_bindings = json.loads(args.task_bindings_json) if args.task_bindings_json else None
        if expected_task_bindings is not None and not isinstance(expected_task_bindings, list):
            raise ValueError("--task-bindings-json must contain a list")
        supplied_promotion_target_bases = (
            json.loads(args.promotion_target_bases_json) if args.promotion_target_bases_json else {}
        )
        if not isinstance(supplied_promotion_target_bases, dict) or not all(
            isinstance(path, str) and isinstance(digest, str)
            for path, digest in supplied_promotion_target_bases.items()
        ):
            raise ValueError("--promotion-target-bases-json must contain a string mapping")
        ce_plugin_config = validate_ce_plugin_inputs(
            args.arms,
            args.ce_plugin_dir,
            args.ce_plugin_version,
        )
    except (OSError, SandboxError, ValueError, yaml.YAMLError) as exc:
        parser.error(str(exc))
        raise AssertionError("ArgumentParser.error() returned unexpectedly")

    candidate_arms = [arm for arm in args.arms if arm in CANDIDATE_ARMS]
    if candidate_arms and args.candidate_overlay is None:
        parser.error("candidate_* arms require --candidate-overlay")
    if args.candidate_overlay is not None and not candidate_arms:
        parser.error("--candidate-overlay requires at least one candidate_* arm")
    for candidate_arm in candidate_arms:
        incumbent_arm = CANDIDATE_ARMS[candidate_arm]
        if incumbent_arm not in args.arms:
            parser.error(f"{candidate_arm} must be paired with {incumbent_arm}")

View on GitHub (pinned to d540b00184)

Solutions

  1. Ensure the value is a JSON object with string keys and string values, e.g. `{"src/foo.ts": "sha1:abc"}`.
  2. Validate before running: `python3 -c "import json,sys; d=json.load(open(sys.argv[1])); assert isinstance(d,dict) and all(isinstance(k,str) and isinstance(v,str) for k,v in d.items())" bases.json`.
  3. Coerce any numeric digests to strings in the producing script.
  4. If unneeded, omit the flag (defaults to {}).

Example fix

# before — non-string values
--promotion-target-bases-json '{"src/foo.ts": 12345}'
# after — string-to-string mapping
--promotion-target-bases-json '{"src/foo.ts": "sha1:12345"}'
Defensive patterns

Strategy: validation

Validate before calling

import json

v = json.loads(args.promotion_target_bases_json) if args.promotion_target_bases_json else {}
assert isinstance(v, dict) and all(
    isinstance(k, str) and isinstance(val, str) for k, val in v.items()
), '--promotion-target-bases-json must be a string-to-string mapping'

Type guard

def is_string_string_map(raw: str | None) -> bool:
    if not raw:
        return True
    try:
        v = json.loads(raw)
    except json.JSONDecodeError:
        return False
    return isinstance(v, dict) and all(isinstance(k, str) and isinstance(val, str) for k, val in v.items())

Prevention

When it happens

Trigger: json.loads(args.promotion_target_bases_json) yields a non-dict, or a dict where some key or value is not a str — e.g. a list, or a dict with int values like `{"path": 123}`.

Common situations: Emitting the map from a script that left numeric digests as ints; confusing this object flag with the list-shaped --task-bindings-json; passing a JSON array by mistake; non-string keys (tuple/None) from a buggy serializer.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/b9415c8f7551e338. Report an issue: GitHub.