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
- Ensure the value is a JSON object with string keys and string values, e.g. `{"src/foo.ts": "sha1:abc"}`.
- 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`.
- Coerce any numeric digests to strings in the producing script.
- 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
- Serialize digests as strings, not ints, in the producing script.
- Remember task-bindings is a list, promotion-target-bases is a string map.
- Omit the flag when unused (defaults to {}).
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
- --task-bindings-json must contain a list
- task file must contain a tasks list
- Malformed --shard arg '${malformed}' — expected --shard=<ind
- ${source} must be a boolean (true/false).
- ${source} must be a string.
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/b9415c8f7551e338.
Report an issue: GitHub.