{"record":{"id":"b9415c8f7551e338","repo":"abhigyanpatwari/GitNexus","slug":"promotion-target-bases-json-must-contain-a-strin","errorCode":null,"errorMessage":"--promotion-target-bases-json must contain a string mapping","messagePattern":"--promotion-target-bases-json must contain a string mapping","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/runner.py","lineNumber":936,"sourceCode":"        task_document = yaml.safe_load(args.tasks.read_text())\n        if not isinstance(task_document, Mapping) or not isinstance(task_document.get(\"tasks\"), list):\n            raise ValueError(\"task file must contain a tasks list\")\n        tasks, skipped_expensive = select_tasks(\n            task_document[\"tasks\"],\n            include_expensive=args.include_expensive,\n        )\n        oracle_snapshots = capture_task_oracles(tasks)\n        expected_task_bindings = json.loads(args.task_bindings_json) if args.task_bindings_json else None\n        if expected_task_bindings is not None and not isinstance(expected_task_bindings, list):\n            raise ValueError(\"--task-bindings-json must contain a list\")\n        supplied_promotion_target_bases = (\n            json.loads(args.promotion_target_bases_json) if args.promotion_target_bases_json else {}\n        )\n        if not isinstance(supplied_promotion_target_bases, dict) or not all(\n            isinstance(path, str) and isinstance(digest, str)\n            for path, digest in supplied_promotion_target_bases.items()\n        ):\n            raise ValueError(\"--promotion-target-bases-json must contain a string mapping\")\n        ce_plugin_config = validate_ce_plugin_inputs(\n            args.arms,\n            args.ce_plugin_dir,\n            args.ce_plugin_version,\n        )\n    except (OSError, SandboxError, ValueError, yaml.YAMLError) as exc:\n        parser.error(str(exc))\n        raise AssertionError(\"ArgumentParser.error() returned unexpectedly\")\n\n    candidate_arms = [arm for arm in args.arms if arm in CANDIDATE_ARMS]\n    if candidate_arms and args.candidate_overlay is None:\n        parser.error(\"candidate_* arms require --candidate-overlay\")\n    if args.candidate_overlay is not None and not candidate_arms:\n        parser.error(\"--candidate-overlay requires at least one candidate_* arm\")\n    for candidate_arm in candidate_arms:\n        incumbent_arm = CANDIDATE_ARMS[candidate_arm]\n        if incumbent_arm not in args.arms:\n            parser.error(f\"{candidate_arm} must be paired with {incumbent_arm}\")","sourceCodeStart":918,"sourceCodeEnd":954,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/runner.py#L918-L954","documentation":"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).","triggerScenarios":"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}`.","commonSituations":"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.","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 {})."],"exampleFix":"# before — non-string values\n--promotion-target-bases-json '{\"src/foo.ts\": 12345}'\n# after — string-to-string mapping\n--promotion-target-bases-json '{\"src/foo.ts\": \"sha1:12345\"}'","handlingStrategy":"validation","validationCode":"import json\n\nv = json.loads(args.promotion_target_bases_json) if args.promotion_target_bases_json else {}\nassert isinstance(v, dict) and all(\n    isinstance(k, str) and isinstance(val, str) for k, val in v.items()\n), '--promotion-target-bases-json must be a string-to-string mapping'","typeGuard":"def is_string_string_map(raw: str | None) -> bool:\n    if not raw:\n        return True\n    try:\n        v = json.loads(raw)\n    except json.JSONDecodeError:\n        return False\n    return isinstance(v, dict) and all(isinstance(k, str) and isinstance(val, str) for k, val in v.items())","tryCatchPattern":null,"preventionTips":["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 {})."],"tags":["cli","json","validation","promotion","task-config"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}