iflytek/astron-agent · error · OutboundPolicyError

Tool URL has unresolved path parameters

Error message

Tool URL has unresolved path parameters

What it means

After substituting all supplied path parameters, the library scans the final URL for any remaining {placeholder} tokens. If any are left, it means the endpoint template requires parameters that were not supplied, so the request would hit a literal '{...}' path. It raises OutboundPolicyError('Tool URL has unresolved path parameters') to fail closed instead of making a doomed request.

Solutions

  1. Supply a value for every {placeholder} named in the tool's endpoint template in the path parameter map
  2. Regenerate/refresh the tool schema so the client knows all required path parameters
  3. Add client-side validation that all template placeholders have corresponding arguments before calling

Example fix

// before
path = {"userId": "7"}  # template: /users/{userId}/posts/{postId}
// after
path = {"userId": "7", "postId": "33"}
Defensive patterns

Strategy: validation

Validate before calling

import re
def all_placeholders_filled(template, params):
    return not re.search(r"\{([^{}]+)\}", template.replace("{", "{").format(**{}) if False else _substituted(template, params))
def _substituted(t, p):
    for k, v in p.items():
        t = t.replace("{" + str(k) + "}", str(v))
    return t

Try / catch

try:
    result = await run.do_call(span)
except CallThirdApiException as e:
    if 'unresolved path parameters' in str(e.err):
        missing = re.findall(r"\{([^{}]+)\}", expected_url)
        raise MissingToolArgs(missing) from e
    raise

Prevention

When it happens

Trigger: do_call → _build_url where the server URL template contains {placeholders} (e.g. /users/{userId}/posts/{postId}) but self.path does not include all of those keys — a required path parameter was omitted from the tool call arguments.

Common situations: Caller omitted an optional-looking but template-required path variable; schema added a new placeholder after the client was written; LLM-generated tool arguments dropped a parameter.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/438371f2496677de. Report an issue: GitHub.

Appendix: source

Thrown at core/plugin/link/infra/tool_exector/process.py:135

        # persisted endpoint path.
        for name, value in self.path.items():
            placeholder = "{" + str(name) + "}"
            if placeholder not in url:
                raise OutboundPolicyError(
                    f"Tool path parameter has no matching placeholder: {name}"
                )
            raw_value = str(value)
            if (
                raw_value in {".", ".."}
                or "/" in raw_value
                or "\\" in raw_value
                or any(ord(character) < 0x20 for character in raw_value)
            ):
                raise OutboundPolicyError("Tool path parameter is unsafe")
            url = url.replace(placeholder, quote(raw_value, safe=""))

        if _PATH_PARAMETER_PATTERN.search(url):
            raise OutboundPolicyError("Tool URL has unresolved path parameters")

        # Authentication method selection and URL construction
        if self._is_authorization_md5:
            url = public_query_url(url)
            if self.query:
                url = url + "&" + "&".join([f"{k}={v}" for k, v in self.query.items()])
        elif self._is_auth_hmac:
            url, headers = assemble_ws_auth_url(
                url, self.method, self.auth_con_js, self.body
            )
            self.header = headers
        else:
            if self.query:
                url = url + "?" + "&".join([f"{k}={v}" for k, v in self.query.items()])

        # Authentication helpers may add query data, but must not replace the endpoint origin.
        ensure_same_origin(self.server, url)
        return url

View on GitHub (pinned to 5e758547a8)