{"record":{"id":"0c5a9986b757c6c6","repo":"NousResearch/hermes-agent","slug":"transcription-provider-name-must-be-a-non-empty-s","errorCode":null,"errorMessage":"Transcription provider .name must be a non-empty string","messagePattern":"Transcription provider \\.name must be a non-empty string","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/transcription_registry.py","lineNumber":79,"sourceCode":"    Rejects:\n\n    - Non-:class:`TranscriptionProvider` instances (raises :class:`TypeError`).\n    - Empty/whitespace ``.name`` (raises :class:`ValueError`).\n    - Names colliding with a built-in (logs a warning, silently\n      ignores — built-ins-always-win invariant).\n\n    Re-registration (same ``name``) overwrites the previous entry and\n    logs a debug message — makes hot-reload scenarios (tests, dev\n    loops) behave predictably.\n    \"\"\"\n    if not isinstance(provider, TranscriptionProvider):\n        raise TypeError(\n            f\"register_provider() expects a TranscriptionProvider instance, \"\n            f\"got {type(provider).__name__}\"\n        )\n    name = provider.name\n    if not isinstance(name, str) or not name.strip():\n        raise ValueError(\"Transcription provider .name must be a non-empty string\")\n    key = name.strip().lower()\n    if key in _BUILTIN_NAMES:\n        logger.warning(\n            \"Transcription provider '%s' shadows a built-in name; registration \"\n            \"ignored. Built-in STT providers (%s) always win — pick a different \"\n            \"name.\",\n            key, \", \".join(sorted(_BUILTIN_NAMES)),\n        )\n        return\n    with _lock:\n        target = _providers if scope is None else _scoped_providers.setdefault(scope, {})\n        existing = target.get(key)\n        target[key] = provider\n    if existing is not None:\n        logger.debug(\n            \"Transcription provider '%s' re-registered (was %r)\",\n            key, type(existing).__name__,\n        )","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/transcription_registry.py#L61-L97","documentation":"ValueError from TranscriptionProviderRegistry.register_provider() (agent/transcription_registry.py:79) when provider.name is not a non-empty string after strip(). The name is the registry key (normalized via name.strip().lower()), so an empty name would make the provider unreachable and collide with other empty-named entries.","triggerScenarios":"Registering a provider whose .name attribute is '', '   ', None, or a non-string (the isinstance check catches both) — e.g. the name was meant to come from config and config was missing, or a dataclass default of empty string was never overwritten.","commonSituations":"Provider name sourced from a config key that is absent (falls back to ''); copy-pasted provider skeleton with name = '' placeholder; name accidentally assigned to a property that returns None.","solutions":["Set a concrete name on the provider instance/class before register_provider().","If the name comes from config, validate/fail earlier at plugin load with a clear message about the missing key.","Add an assertion or test that the provider exposes a non-empty string name."],"exampleFix":"# before\nclass MyProvider(TranscriptionProvider):\n    name = ''  # never set -> ValueError on register\n\n# after\nclass MyProvider(TranscriptionProvider):\n    name = 'my-stt'","handlingStrategy":"validation","validationCode":"def has_valid_provider_name(provider) -> bool:\n    name = getattr(provider, \"name\", None)\n    return isinstance(name, str) and bool(name.strip())","typeGuard":null,"tryCatchPattern":"try:\n    register_provider(provider)\nexcept ValueError as exc:\n    raise ConfigError(f\"stt provider misconfigured: {exc}\") from exc","preventionTips":["Make provider .name a required constructor argument, not an optional default.","Validate names at plugin load time with a clear message naming the plugin."],"tags":["validation","plugin","stt","registry"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}