iflytek/astron-agent · warning · RuntimeError

Skill resource is unavailable

Error message

Skill resource is unavailable

What it means

RuntimeError(SKILL_RESOURCE_ERROR) ('Skill resource is unavailable') raised in SkillPlugin._download_text (skill.py:250). The skill resource was downloaded within the byte limit, but its bytes are not valid UTF-8, so decoding with errors='strict' raises UnicodeDecodeError, which is converted into this user-facing error. It protects downstream consumers (LLM prompts, sandbox) from binary garbage masquerading as skill text.

Solutions

  1. Re-upload the skill resource as a UTF-8 text file (convert encoding, e.g. iconv -f GBK -t UTF-8).
  2. Verify the download_url actually points to the text file and not a binary or HTML error page; fetch it and run `file` on it.
  3. Only mark text-decodable files as downloadable skill resources; exclude binaries at skill-publish time.
  4. If the content is legitimately non-text, serve it as a sandbox file resource rather than inline skill text.

Example fix

// before
value = await download_skill_resource(session, url, MAX_SKILL_TEXT_BYTES)
return value.decode("utf-8", errors="strict")
// after: tolerate BOM / pick a fallback before failing
value = await download_skill_resource(session, url, MAX_SKILL_TEXT_BYTES)
if value.startswith(codecs.BOM_UTF8):
    value = value[len(codecs.BOM_UTF8):]
try:
    return value.decode("utf-8")
except UnicodeDecodeError:
    return value.decode("utf-8", errors="replace")
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_utf8(data: bytes) -> bool:
    try:
        data.decode("utf-8")
        return True
    except UnicodeDecodeError:
        return False
# call before treating the download as skill text
if not is_valid_utf8(value):
    raise RuntimeError(SKILL_RESOURCE_ERROR)

Type guard

def looks_like_text(data: bytes) -> bool:
    text_chars = bytes(range(32, 127)) + b"\n\r\t"
    return not bool(data.translate(None, delete=text_chars))

Try / catch

try:
    text = await plugin._download_text(url)
except RuntimeError as e:
    if str(e) == SKILL_RESOURCE_ERROR:
        logger.warning("skill resource %s is not valid UTF-8 text; skipping", url)
    raise

Prevention

When it happens

Trigger: Downloading a skill resource whose download_url points to a binary file (zip, pdf, image, or non-UTF-8 encoded text) instead of UTF-8 text, then attempting decode.

Common situations: Skill author uploaded a binary asset or a file saved with a non-UTF-8 encoding (GBK, UTF-16, Latin-1), or the URL redirects to an error page/CDN binary response instead of the text resource.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at core/agent/service/plugin/skill.py:250

                }
                return PluginResponse(result=result)

        return _runner

    def _normalize_path(self, value: Any) -> str:
        path = str(value or "").strip().replace("\\", "/")
        while path.startswith("./"):
            path = path[2:]
        return path.lstrip("/")

    async def _download_text(self, url: str) -> str:
        timeout = aiohttp.ClientTimeout(total=30)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            value = await download_skill_resource(session, url, MAX_SKILL_TEXT_BYTES)
        try:
            return value.decode("utf-8", errors="strict")
        except UnicodeDecodeError:
            raise RuntimeError(SKILL_RESOURCE_ERROR) from None

View on GitHub (pinned to 5e758547a8)