{"record":{"id":"4d2bb2597b1f538a","repo":"NousResearch/hermes-agent","slug":"unknown-toolsets-join-sorted-unknown","errorCode":null,"errorMessage":"Unknown toolsets: {', '.join(sorted(unknown))}.","messagePattern":"Unknown toolsets: (.+?)\\.","errorType":"exception","errorClass":"SubagentLifecycleError","httpStatus":null,"severity":"error","filePath":"agent/subagent_lifecycle.py","lineNumber":531,"sourceCode":"            )\n        if request.blocked_tools:\n            raise SubagentLifecycleError(\n                \"Per-tool blocking is not supported; use allowed_toolsets. Hermes always blocks unsafe child tools.\"\n            )\n        try:\n            metadata_bytes = len(\n                json.dumps(dict(request.metadata), sort_keys=True).encode()\n            )\n        except (TypeError, ValueError) as exc:\n            raise SubagentLifecycleError(\"metadata must be JSON-serializable.\") from exc\n        if metadata_bytes > _MAX_METADATA_BYTES:\n            raise SubagentLifecycleError(\"metadata exceeds 8192 bytes.\")\n        if request.allowed_toolsets:\n            from toolsets import TOOLSETS\n\n            unknown = set(request.allowed_toolsets) - set(TOOLSETS)\n            if unknown:\n                raise SubagentLifecycleError(\n                    f\"Unknown toolsets: {', '.join(sorted(unknown))}.\"\n                )\n            enabled = getattr(parent, \"enabled_toolsets\", None)\n            if enabled is not None and not set(request.allowed_toolsets).issubset(\n                set(enabled)\n            ):\n                raise SubagentLifecycleError(\n                    \"Requested toolsets would broaden parent permissions.\"\n                )\n","sourceCodeStart":513,"sourceCodeEnd":541,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/subagent_lifecycle.py#L513-L541","documentation":"Validation error from SubagentLifecycleManager._validate_request(): every name in request.allowed_toolsets must be a key of the TOOLSETS dict in toolsets.py. Unknown names (typos, removed toolsets, custom toolset names not registered in TOOLSETS) are reported sorted in the message.","triggerScenarios":"Passing allowed_toolsets=[\"filesystem\"] instead of \"file\"; referencing a toolset that was renamed or removed in a Hermes upgrade; using a plugin toolset name that lives only in the plugin registry, not in TOOLSETS; casing mistakes (\"Web\" vs \"web\").","commonSituations":"Hardcoding toolset lists across Hermes versions; copying toolset names from old docs or another repo; plugin authors assuming plugin toolsets are addressable here.","solutions":["Validate names against toolsets.TOOLSETS before launching and fix typos/casing.","After upgrading Hermes, re-check that your toolset names still exist (grep TOOLSETS in toolsets.py).","For plugin-provided toolsets, register them in the toolset registry or launch without allowed_toolsets and rely on the parent's enabled set."],"exampleFix":"# before\nrequest = SubagentLaunchRequest(goal=g, allowed_toolsets=[\"filesystem\", \"Web\"])\n\n# after\nfrom toolsets import TOOLSETS\nwanted = [t for t in (\"file\", \"web\") if t in TOOLSETS]\nrequest = SubagentLaunchRequest(goal=g, allowed_toolsets=wanted)","handlingStrategy":"validation","validationCode":"from toolsets import TOOLSETS\nwanted = [t for t in requested_toolsets if t in TOOLSETS]\ndropped = set(requested_toolsets) - set(wanted)\nif dropped:\n    log.warning(\"dropping unknown toolsets: %s\", dropped)\nrequest = SubagentLaunchRequest(goal=goal, allowed_toolsets=wanted)","typeGuard":"from toolsets import TOOLSETS\n\ndef are_known_toolsets(names) -> bool:\n    return set(names) <= set(TOOLSETS)","tryCatchPattern":"try:\n    manager.launch(request)\nexcept SubagentLifecycleError as exc:\n    if str(exc).startswith(\"Unknown toolsets\"):\n        request = dataclasses.replace(\n            request,\n            allowed_toolsets=[t for t in request.allowed_toolsets if t in TOOLSETS],\n        )\n        manager.launch(request)\n    else:\n        raise","preventionTips":["Source toolset names from toolsets.TOOLSETS, never from memory or old docs.","Re-validate hardcoded toolset lists after every Hermes upgrade.","Check casing — toolset keys are lower-case."],"tags":["subagents","delegation","toolsets","validation"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}