{"record":{"id":"eb2f8b495064e4f6","repo":"OpenBMB/ChatDev","slug":"package-entries-must-be-strings","errorCode":null,"errorMessage":"package entries must be strings","messagePattern":"package entries must be strings","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"functions/function_calling/uv_related.py","lineNumber":68,"sourceCode":"            raise ValueError(\"python_workspace_root missing from _context\")\n        path = Path(raw_path).expanduser().resolve()\n        path.mkdir(parents=True, exist_ok=True)\n        return path\n\n    def resolve_under_workspace(self, relative_path: str | Path) -> Path:\n        candidate = Path(relative_path)\n        absolute = candidate if candidate.is_absolute() else self.workspace_root / candidate\n        absolute = absolute.expanduser().resolve()\n        if self.workspace_root not in absolute.parents and absolute != self.workspace_root:\n            raise ValueError(\"script path is outside workspace root\")\n        return absolute\n\n\ndef _validate_packages(packages: Sequence[str]) -> List[str]:\n    normalized: List[str] = []\n    for pkg in packages:\n        if not isinstance(pkg, str):\n            raise ValueError(\"package entries must be strings\")\n        stripped = pkg.strip()\n        if not stripped:\n            raise ValueError(\"package names cannot be empty\")\n        if not _SAFE_PACKAGE_RE.match(stripped):\n            raise ValueError(f\"unsafe characters detected in package spec {pkg}\")\n        if stripped.startswith(\"-\"):\n            raise ValueError(f\"flags are not allowed in packages list: {pkg}\")\n        normalized.append(stripped)\n    if not normalized:\n        raise ValueError(\"at least one package is required\")\n    return normalized\n\n\ndef _coerce_timeout_seconds(timeout_seconds: Any) -> float | None:\n    if timeout_seconds is None:\n        return None\n    if isinstance(timeout_seconds, bool):\n        raise ValueError(\"timeout_seconds must be a number\")","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/functions/function_calling/uv_related.py#L50-L86","documentation":"install_python_packages validates every entry in its packages list and requires each to be a string. Non-string entries (None, numbers, lists/dicts from malformed JSON) raise ValueError before any uv command runs. This front-loads type validation so bad payloads fail fast.","triggerScenarios":"Passing packages=[\"numpy\", 42] or packages=[None]; JSON tool args where an element is a number or nested object; unpacking a tuple/iterable of mixed types into the list.","commonSituations":"LLM tool-call payloads with mixed-type arrays; config files parsed without schema validation; programmatic lists built from untyped inputs.","solutions":["Ensure every packages entry is a str","Validate/cast entries (e.g. str(p) only when sensible) before calling","Add a JSON schema requiring items.type=string for the packages array in your tool definition"],"exampleFix":"# before\ninstall_python_packages(packages=[\"numpy\", 42])\n# after\ninstall_python_packages(packages=[\"numpy\", \"pydantic\"])","handlingStrategy":"type-guard","validationCode":"packages = [p for p in packages if isinstance(p, str) and p.strip()]\ninstall_python_packages(packages=packages, _context=ctx)","typeGuard":"def all_strings(items) -> bool:\n    return all(isinstance(i, str) for i in items)","tryCatchPattern":"try:\n    install_python_packages(packages=packages, _context=ctx)\nexcept ValueError as e:\n    if \"must be strings\" in str(e):\n        packages = [str(p) for p in packages if p]\n        install_python_packages(packages=packages, _context=ctx)\n    else:\n        raise","preventionTips":["Schema-require packages as array of strings","Filter/cast mixed-type lists at the boundary","Never build the list from untyped user input directly"],"tags":["validation","uv","packages","type-mismatch"],"backgroundTag":"invalid-argument-type","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}