{"record":{"id":"811fb6490c8f0c72","repo":"NousResearch/hermes-agent","slug":"refusing-non-petdex-spritesheet-host-for-slug","errorCode":null,"errorMessage":"refusing non-petdex spritesheet host for '{slug}'","messagePattern":"refusing non-petdex spritesheet host for '(.+?)'","errorType":"exception","errorClass":"PetStoreError","httpStatus":null,"severity":"error","filePath":"agent/pet/store.py","lineNumber":176,"sourceCode":"    \"\"\"\n    from agent.pet.manifest import find_entry\n\n    slug = _safe_slug(slug)\n    if not slug:\n        raise PetStoreError(\"invalid pet slug\")\n    existing = load_pet(slug)\n    if existing and existing.exists and not force:\n        return existing\n\n    entry = find_entry(slug, timeout=timeout)\n    if entry is None:\n        raise PetStoreError(f\"pet '{slug}' is not in the petdex manifest\")\n\n    # Host-pin every asset URL to petdex. The manifest is trusted (HTTPS from\n    # petdex.dev), but pin the asset hosts too so a compromised/spoofed manifest\n    # can't redirect the download at an arbitrary host. Matches thumbnail_png.\n    if not _is_petdex_host(entry.spritesheet_url):\n        raise PetStoreError(f\"refusing non-petdex spritesheet host for '{slug}'\")\n\n    directory = pets_dir() / slug\n    directory.mkdir(parents=True, exist_ok=True)\n\n    sprite_ext = \".png\" if entry.spritesheet_url.lower().split(\"?\")[0].endswith(\".png\") else \".webp\"\n    sprite_path = directory / f\"spritesheet{sprite_ext}\"\n\n    _download(entry.spritesheet_url, sprite_path, timeout=timeout)\n\n    # Fetch the upstream pet.json if present; otherwise synthesize a minimal\n    # one so the local layout is self-describing.\n    meta: dict = {}\n    if entry.pet_json_url and _is_petdex_host(entry.pet_json_url):\n        try:\n            meta = _download_json(entry.pet_json_url, timeout=timeout)\n        except Exception as exc:  # noqa: BLE001 - non-fatal, fall back below\n            logger.debug(\"pet.json fetch failed for %s: %s\", slug, exc)\n    if not isinstance(meta, dict) or not meta:","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/pet/store.py#L158-L194","documentation":"Error \"refusing non-petdex spritesheet host for '{slug}'\" thrown in NousResearch/hermes-agent.","triggerScenarios":"Thrown at agent/pet/store.py:176 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Only install pets whose spritesheets are hosted on the official petdex host.","Report the manifest entry if it points at an unexpected host."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}