{"record":{"id":"72c6aa5222d64350","repo":"iflytek/astron-agent","slug":"tool-path-parameter-has-no-matching-placeholder-name","errorCode":null,"errorMessage":"Tool path parameter has no matching placeholder: {name}","messagePattern":"Tool path parameter has no matching placeholder: (.+?)","errorType":"exception","errorClass":"OutboundPolicyError","httpStatus":null,"severity":"error","filePath":"core/plugin/link/infra/tool_exector/process.py","lineNumber":121,"sourceCode":"                err_pre=ErrCode.SERVER_VALIDATE_ERR.msg,\n                err=str(exc),\n            ) from exc\n\n    def _build_url(self) -> str:\n        \"\"\"Build request URL with authentication and query parameters.\n\n        Returns:\n            str: Complete URL for the request\n        \"\"\"\n        url = self.server\n\n        # Substitute OpenAPI path parameters as individual path segments. urljoin is unsafe here:\n        # an absolute value, a scheme-relative value, or a dot segment can replace/escape the\n        # persisted endpoint path.\n        for name, value in self.path.items():\n            placeholder = \"{\" + str(name) + \"}\"\n            if placeholder not in url:\n                raise OutboundPolicyError(\n                    f\"Tool path parameter has no matching placeholder: {name}\"\n                )\n            raw_value = str(value)\n            if (\n                raw_value in {\".\", \"..\"}\n                or \"/\" in raw_value\n                or \"\\\\\" in raw_value\n                or any(ord(character) < 0x20 for character in raw_value)\n            ):\n                raise OutboundPolicyError(\"Tool path parameter is unsafe\")\n            url = url.replace(placeholder, quote(raw_value, safe=\"\"))\n\n        if _PATH_PARAMETER_PATTERN.search(url):\n            raise OutboundPolicyError(\"Tool URL has unresolved path parameters\")\n\n        # Authentication method selection and URL construction\n        if self._is_authorization_md5:\n            url = public_query_url(url)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/plugin/link/infra/tool_exector/process.py#L103-L139","documentation":"When substituting OpenAPI path parameters into the endpoint URL, each configured path variable must match a {placeholder} in the server URL. If a parameter named in the tool's path map has no corresponding {name} placeholder in the URL, the library raises OutboundPolicyError rather than silently dropping or appending the parameter. This is fail-closed behavior preventing parameters from being misplaced or injected elsewhere in the URL.","triggerScenarios":"do_call → _build_url where self.path contains a key (e.g. 'petId') but the server URL has no '{petId}' placeholder — typically because the registered endpoint template lacks the placeholder or the parameter name differs in case/spelling.","commonSituations":"Tool OpenAPI schema edited so the endpoint template no longer contains the placeholder; client supplies extra path parameters not declared in the template; placeholder renamed (e.g. {pet_id} vs {petId}) in schema or caller.","solutions":["Compare the parameter name in the message against the {placeholders} in the tool's server URL and make them match exactly","Update the tool's OpenAPI schema so the endpoint template includes the required placeholder, e.g. https://api.example.com/pets/{petId}","Remove the extraneous path parameter from the request if it is not part of the endpoint"],"exampleFix":"// before\npath = {\"petId\": 42}  # server = \"https://api.example.com/pets\"\n// after\npath = {\"petId\": 42}  # server = \"https://api.example.com/pets/{petId}\"","handlingStrategy":"validation","validationCode":"import re\ndef path_params_match(template, params):\n    placeholders = set(re.findall(r\"\\{([^{}]+)\\}\", template))\n    return all((\"{\" + k + \"}\") in placeholders for k in params)","typeGuard":null,"tryCatchPattern":"try:\n    result = await run.do_call(span)\nexcept CallThirdApiException as e:\n    if 'no matching placeholder' in str(e.err):\n        fix_tool_schema_or_params(e.err)\n    raise","preventionTips":["Validate tool schemas at registration: every declared path param must exist as a placeholder","Keep parameter names identical between schema and callers","Add a schema lint step in CI for tool definitions"],"tags":["python","openapi","url-template"],"backgroundTag":"missing-required-argument","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}