{"record":{"id":"7bbb3a763b2a248d","repo":"HKUDS/Vibe-Trading","slug":"run-id-must-not-be-empty","errorCode":null,"errorMessage":"run_id must not be empty","messagePattern":"run_id must not be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/governance/manifest.py","lineNumber":392,"sourceCode":"            caller already has the injected skills' full bodies) or a\n            pre-built sequence of :class:`SkillRecord`.\n        tool_names: Tool registry names, e.g. ``ToolRegistry.tool_names``.\n        package_versions: ``{package: version_or_None}``; see\n            :func:`collect_key_package_versions` for a ready-made curated\n            collector.\n        extra: Small caller-defined composition dimensions (e.g.\n            ``{\"provider\": \"openrouter\", \"model\": \"deepseek/deepseek-v3.2\"}``).\n\n    Returns:\n        A new :class:`RunManifest` with ``manifest_hash`` computed over the\n        composition (excluding ``run_id``/``timestamp``).\n\n    Raises:\n        ValueError: ``run_id``/``timestamp`` is empty, or ``skills`` contains\n            two records with the same name.\n    \"\"\"\n    if not run_id or not run_id.strip():\n        raise ValueError(\"run_id must not be empty\")\n    if not timestamp or not timestamp.strip():\n        raise ValueError(\"timestamp must not be empty\")\n\n    if isinstance(skills, Mapping):\n        skill_records = tuple(\n            sorted(\n                (SkillRecord.from_content(name, content) for name, content in skills.items()),\n                key=lambda record: record.name,\n            )\n        )\n    else:\n        skill_records = tuple(sorted(skills, key=lambda record: record.name))\n        names = [record.name for record in skill_records]\n        if len(names) != len(set(names)):\n            raise ValueError(f\"duplicate skill names in manifest input: {names}\")\n\n    tools_snapshot = ToolRegistrySnapshot.from_names(tool_names)\n    pv_pairs = _pairs(package_versions)","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/governance/manifest.py#L374-L410","documentation":"build_run_manifest requires a non-empty run_id (after strip). Empty or whitespace-only ids are rejected because the manifest must be attributable to a concrete run.","triggerScenarios":"Calling build_run_manifest(run_id=\"\"), run_id=\"   \", or passing an unpopulated variable (None-ish default resolved to empty string).","commonSituations":"run id generated only in a code path not taken (e.g. resumed run); env/config supplying an empty RUN_ID; tests calling the builder with placeholder ids.","solutions":["Generate the run id up front (uuid or run registry) and thread it through to the manifest call","Validate run_id.strip() at the entry point of the run, not at manifest time","Fail fast in tests with a fixture-provided non-empty id"],"exampleFix":"# before\nmanifest = build_run_manifest(run_id=run_id, ...)  # run_id == \"\"\n# after\nrun_id = run_id or f\"run-{uuid.uuid4().hex}\"\nmanifest = build_run_manifest(run_id=run_id, ...)","handlingStrategy":"validation","validationCode":"run_id = (run_id or \"\").strip() or f\"run-{uuid.uuid4().hex}\"","typeGuard":"def is_valid_run_id(run_id: str) -> bool:\n    return bool(run_id and run_id.strip())","tryCatchPattern":"except ValueError as e: if 'run_id' in str(e): generate an id and retry build_run_manifest","preventionTips":["Assign the run id at run start, not lazily","Validate ids at the entry point","Use a run registry to guarantee uniqueness/non-emptiness"],"tags":["manifest","run-id","missing-required-field","python"],"backgroundTag":"missing-required-field","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}